KiCad PCB EDA Suite
pgm_base.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) 2008 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
33 #include <fctsys.h>
34 #include <wx/html/htmlwin.h>
35 #include <wx/fs_zip.h>
36 #include <wx/dir.h>
37 #include <wx/filename.h>
38 #include <wx/snglinst.h>
39 #include <wx/stdpaths.h>
40 #include <wx/sysopt.h>
41 #include <wx/richmsgdlg.h>
42 
43 #include <pgm_base.h>
44 #include <eda_base_frame.h>
45 #include <macros.h>
46 #include <config_params.h>
47 #include <id.h>
48 #include <build_version.h>
49 #include <hotkeys_basic.h>
50 #include <gestfich.h>
51 #include <menus_helpers.h>
52 #include <confirm.h>
53 #include <dialog_env_var_config.h>
54 #include <lockfile.h>
55 #include <systemdirsappend.h>
56 
57 
58 #define KICAD_COMMON wxT( "kicad_common" )
59 
60 // some key strings used to store parameters in KICAD_COMMON
61 
62 const wxChar PGM_BASE::workingDirKey[] = wxT( "WorkingDir" ); // public
63 
64 static const wxChar languageCfgKey[] = wxT( "LanguageID" );
65 static const wxChar pathEnvVariables[] = wxT( "EnvironmentVariables" );
66 static const wxChar showEnvVarWarningDialog[] = wxT( "ShowEnvVarWarningDialog" );
67 static const wxChar traceEnvVars[] = wxT( "KIENVVARS" );
69 static const wxChar entryUseIconsInMenus[] = wxT( "UseIconsInMenus" );
70 
71 
81 {
84 
87 
90 
92  wxString m_Lang_Label;
93 
96 };
97 
98 
106 {
107  // Default language
108  {
109  wxLANGUAGE_DEFAULT,
111  lang_def_xpm,
112  _( "Default" )
113  },
114 
115  // English language
116  {
117  wxLANGUAGE_ENGLISH,
119  lang_en_xpm,
120  wxT( "English" ),
121  true
122  },
123 
124  // French language
125  {
126  wxLANGUAGE_FRENCH,
128  lang_fr_xpm,
129  _( "French" )
130  },
131 
132  // Finnish language
133  {
134  wxLANGUAGE_FINNISH,
136  lang_fi_xpm,
137  _( "Finnish" )
138  },
139 
140  // Spanish language
141  {
142  wxLANGUAGE_SPANISH,
144  lang_es_xpm,
145  _( "Spanish" )
146  },
147 
148  // Portuguese language
149  {
150  wxLANGUAGE_PORTUGUESE,
152  lang_pt_xpm,
153  _( "Portuguese" )
154  },
155 
156  // Italian language
157  {
158  wxLANGUAGE_ITALIAN,
160  lang_it_xpm,
161  _( "Italian" )
162  },
163 
164  // German language
165  {
166  wxLANGUAGE_GERMAN,
168  lang_de_xpm,
169  _( "German" )
170  },
171 
172  // Greek language
173  {
174  wxLANGUAGE_GREEK,
176  lang_gr_xpm,
177  _( "Greek" )
178  },
179 
180  // Slovenian language
181  {
182  wxLANGUAGE_SLOVENIAN,
184  lang_sl_xpm,
185  _( "Slovenian" )
186  },
187 
188  // Slovenian language
189  {
190  wxLANGUAGE_SLOVAK,
192  lang_sk_xpm,
193  _( "Slovak" )
194  },
195 
196  // Hungarian language
197  {
198  wxLANGUAGE_HUNGARIAN,
200  lang_hu_xpm,
201  _( "Hungarian" )
202  },
203 
204  // Polish language
205  {
206  wxLANGUAGE_POLISH,
208  lang_pl_xpm,
209  _( "Polish" )
210  },
211 
212  // Czech language
213  {
214  wxLANGUAGE_CZECH,
216  lang_cs_xpm,
217  _( "Czech" )
218  },
219 
220  // Russian language
221  {
222  wxLANGUAGE_RUSSIAN,
224  lang_ru_xpm,
225  _( "Russian" )
226  },
227 
228  // Korean language
229  {
230  wxLANGUAGE_KOREAN,
232  lang_ko_xpm,
233  _( "Korean" )
234  },
235 
236  // Chinese simplified
237  {
238  wxLANGUAGE_CHINESE_SIMPLIFIED,
240  lang_chinese_xpm,
241  _( "Chinese simplified" )
242  },
243 
244  // Catalan language
245  {
246  wxLANGUAGE_CATALAN,
248  lang_catalan_xpm,
249  _( "Catalan" )
250  },
251 
252  // Dutch language
253  {
254  wxLANGUAGE_DUTCH,
256  lang_nl_xpm,
257  _( "Dutch" )
258  },
259 
260  // Japanese language
261  {
262  wxLANGUAGE_JAPANESE,
264  lang_jp_xpm,
265  _( "Japanese" )
266  },
267 
268  // Bulgarian language
269  {
270  wxLANGUAGE_BULGARIAN,
272  lang_bg_xpm,
273  _( "Bulgarian" )
274  },
275 
276  // Lithuanian language
277  {
278  wxLANGUAGE_LITHUANIAN,
280  lang_lt_xpm,
281  _( "Lithuanian" )
282  }
283 };
284 
285 
287 {
288  m_pgm_checker = NULL;
289  m_locale = NULL;
290  m_common_settings = NULL;
291  m_iconsScale = 1.0;
292  m_useIconsInMenus = true; // will be set later after reading the config
293 
294  m_show_env_var_dialog = true;
295 
296  setLanguageId( wxLANGUAGE_DEFAULT );
297 
298  ForceSystemPdfBrowser( false );
299 }
300 
301 
303 {
304  Destroy();
305 }
306 
307 
309 {
310  // unlike a normal destructor, this is designed to be called more than once safely:
311 
312  delete m_common_settings;
313  m_common_settings = 0;
314 
315  delete m_pgm_checker;
316  m_pgm_checker = 0;
317 
318  delete m_locale;
319  m_locale = 0;
320 }
321 
322 
324 {
325  wxASSERT( wxTheApp );
326  return *wxTheApp;
327 }
328 
329 
330 void PGM_BASE::SetEditorName( const wxString& aFileName )
331 {
332  m_editor_name = aFileName;
333  wxASSERT( m_common_settings );
334  m_common_settings->Write( wxT( "Editor" ), aFileName );
335 }
336 
337 
338 const wxString& PGM_BASE::GetEditorName( bool aCanShowFileChooser )
339 {
340  wxString editorname = m_editor_name;
341 
342  if( !editorname )
343  {
344  if( !wxGetEnv( wxT( "EDITOR" ), &editorname ) )
345  {
346  // If there is no EDITOR variable set, try the desktop default
347 #ifdef __WXMAC__
348  editorname = "/usr/bin/open";
349 #elif __WXX11__
350  editorname = "/usr/bin/xdg-open";
351 #endif
352  }
353  }
354 
355  // If we still don't have an editor name show a dialog asking the user to select one
356  if( !editorname && aCanShowFileChooser )
357  {
358  DisplayInfoMessage( NULL,
359  _( "No default editor found, you must choose it" ) );
360 
361  editorname = AskUserForPreferredEditor();
362  }
363 
364  // If we finally have a new editor name request it to be copied to m_editor_name and
365  // saved to the preferences file.
366  if( !editorname.IsEmpty() )
367  SetEditorName( editorname );
368 
369  // m_editor_name already has the same value that editorname, or empty if no editor was
370  // found/chosen.
371  return m_editor_name;
372 }
373 
374 
375 const wxString PGM_BASE::AskUserForPreferredEditor( const wxString& aDefaultEditor )
376 {
377  // Create a mask representing the executable files in the current platform
378 #ifdef __WINDOWS__
379  wxString mask( _( "Executable file (*.exe)|*.exe" ) );
380 #else
381  wxString mask( _( "Executable file (*)|*" ) );
382 #endif
383 
384  // Extract the path, name and extension from the default editor (even if the editor's
385  // name was empty, this method will succeed and return empty strings).
386  wxString path, name, ext;
387  wxFileName::SplitPath( aDefaultEditor, &path, &name, &ext );
388 
389  // Show the modal editor and return the file chosen (may be empty if the user cancels
390  // the dialog).
391  return EDA_FILE_SELECTOR( _( "Select Preferred Editor" ), path,
392  name, ext, mask,
393  NULL, wxFD_OPEN | wxFD_FILE_MUST_EXIST,
394  true );
395 }
396 
397 
399 {
400  wxFileName pgm_name( App().argv[0] );
401 
402  wxConfigBase::DontCreateOnDemand();
403 
404  wxInitAllImageHandlers();
405 
406  m_pgm_checker = new wxSingleInstanceChecker( pgm_name.GetName().Lower() + wxT( "-" ) +
407  wxGetUserId(), GetKicadLockFilePath() );
408 
409  if( m_pgm_checker->IsAnotherRunning() )
410  {
411  wxString quiz = wxString::Format(
412  _( "%s is already running. Continue?" ),
413  GetChars( pgm_name.GetName() )
414  );
415 
416  if( !IsOK( NULL, quiz ) )
417  return false;
418  }
419 
420  // Init KiCad environment
421  // the environment variable KICAD (if exists) gives the kicad path:
422  // something like set KICAD=d:\kicad
423  bool isDefined = wxGetEnv( wxT( "KICAD" ), &m_kicad_env );
424 
425  if( isDefined ) // ensure m_kicad_env ends by "/"
426  {
427  m_kicad_env.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
428 
429  if( !m_kicad_env.IsEmpty() && m_kicad_env.Last() != '/' )
430  m_kicad_env += UNIX_STRING_DIR_SEP;
431  }
432 
433  // Init parameters for configuration
434  App().SetVendorName( wxT( "KiCad" ) );
435  App().SetAppName( pgm_name.GetName().Lower() );
436 
437  // Install some image handlers, mainly for help
438  if( wxImage::FindHandler( wxBITMAP_TYPE_PNG ) == NULL )
439  wxImage::AddHandler( new wxPNGHandler );
440 
441  if( wxImage::FindHandler( wxBITMAP_TYPE_GIF ) == NULL )
442  wxImage::AddHandler( new wxGIFHandler );
443 
444  if( wxImage::FindHandler( wxBITMAP_TYPE_JPEG ) == NULL )
445  wxImage::AddHandler( new wxJPEGHandler );
446 
447  wxFileSystem::AddHandler( new wxZipFSHandler );
448 
449  // Analyze the command line & initialize the binary path
450  setExecutablePath();
451 
452  SetLanguagePath();
453 
454  // OS specific instantiation of wxConfigBase derivative:
455  m_common_settings = GetNewConfig( KICAD_COMMON );
456 
457  wxString envVarName = wxT( "KIGITHUB" );
458  ENV_VAR_ITEM envVarItem;
459  wxString envValue;
460  wxFileName tmpFileName;
461 
462  if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
463  {
464  tmpFileName.AssignDir( envValue );
465  envVarItem.SetDefinedExternally( true );
466  }
467  else
468  {
469  envVarItem.SetValue( wxString( wxT( "https://github.com/KiCad" ) ) );
470  envVarItem.SetDefinedExternally( false );
471  }
472 
473  m_local_env_vars[ envVarName ] = envVarItem;
474 
475  wxFileName baseSharePath;
476  baseSharePath.AssignDir( wxString( wxT( DEFAULT_INSTALL_PATH ) ) );
477 
478 #if !defined( __WXMAC__ )
479  baseSharePath.AppendDir( wxT( "share" ) );
480  baseSharePath.AppendDir( wxT( "kicad" ) );
481 #endif
482 
483  // KISYSMOD
484  envVarName = wxT( "KISYSMOD" );
485 
486  if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
487  {
488  tmpFileName.AssignDir( envValue );
489  envVarItem.SetDefinedExternally( true );
490  }
491  else
492  {
493  tmpFileName = baseSharePath;
494  tmpFileName.AppendDir( wxT( "modules" ) );
495  envVarItem.SetDefinedExternally( false );
496  }
497 
498  envVarItem.SetValue( tmpFileName.GetPath() );
499  m_local_env_vars[ envVarName ] = envVarItem;
500 
501  // KISYS3DMOD
502  envVarName = wxT( "KISYS3DMOD" );
503 
504  if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
505  {
506  tmpFileName.AssignDir( envValue );
507  envVarItem.SetDefinedExternally( true );
508  }
509  else
510  {
511  tmpFileName.AppendDir( wxT( "packages3d" ) );
512  envVarItem.SetDefinedExternally( false );
513  }
514 
515  envVarItem.SetValue( tmpFileName.GetFullPath() );
516  m_local_env_vars[ envVarName ] = envVarItem;
517 
518  // KICAD_TEMPLATE_DIR
519  envVarName = "KICAD_TEMPLATE_DIR";
520 
521  if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
522  {
523  tmpFileName.AssignDir( envValue );
524  envVarItem.SetDefinedExternally( true );
525  }
526  else
527  {
528  // Attempt to find the best default template path.
529  SEARCH_STACK bases;
530  SEARCH_STACK templatePaths;
531 
532  SystemDirsAppend( &bases );
533 
534  for( unsigned i = 0; i < bases.GetCount(); ++i )
535  {
536  wxFileName fn( bases[i], wxEmptyString );
537 
538  // Add KiCad template file path to search path list.
539  fn.AppendDir( "template" );
540 
541  // Only add path if exists and can be read by the user.
542  if( fn.DirExists() && fn.IsDirReadable() )
543  {
544  wxLogDebug( "Checking template path '%s' exists", fn.GetPath() );
545  templatePaths.AddPaths( fn.GetPath() );
546  }
547  }
548 
549  if( templatePaths.IsEmpty() )
550  {
551  tmpFileName = baseSharePath;
552  tmpFileName.AppendDir( "template" );
553  }
554  else
555  {
556  // Take the first one. There may be more but this will likely be the best option.
557  tmpFileName.AssignDir( templatePaths[0] );
558  }
559 
560  envVarItem.SetDefinedExternally( false );
561  }
562 
563  envVarItem.SetValue( tmpFileName.GetPath() );
564  m_local_env_vars[ envVarName ] = envVarItem;
565 
566  // KICAD_USER_TEMPLATE_DIR
567  envVarName = "KICAD_USER_TEMPLATE_DIR";
568 
569  if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
570  {
571  tmpFileName.AssignDir( envValue );
572  envVarItem.SetDefinedExternally( true );
573  }
574  else
575  {
576  // Default user template path.
577  tmpFileName = wxStandardPaths::Get().GetDocumentsDir();
578  tmpFileName.AppendDir( "kicad" );
579  tmpFileName.AppendDir( "template" );
580  envVarItem.SetDefinedExternally( false );
581  }
582 
583  envVarItem.SetValue( tmpFileName.GetPath() );
584  m_local_env_vars[ envVarName ] = envVarItem;
585 
586  // KICAD_SYMBOLS
587  envVarName = wxT( "KICAD_SYMBOL_DIR" );
588 
589  if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
590  {
591  tmpFileName.AssignDir( envValue );
592  envVarItem.SetDefinedExternally( true );
593  }
594  else
595  {
596  tmpFileName = baseSharePath;
597  tmpFileName.AppendDir( wxT( "library" ) );
598  envVarItem.SetDefinedExternally( false );
599  }
600 
601  envVarItem.SetValue( tmpFileName.GetPath() );
602  m_local_env_vars[ envVarName ] = envVarItem;
603 
604  ReadPdfBrowserInfos(); // needs m_common_settings
605 
606  // Init user language *before* calling loadCommonSettings, because
607  // env vars could be incorrectly initialized on Linux
608  // (if the value contains some non ASCII7 chars, the env var is not initialized)
609  SetLanguage( true );
610 
611  loadCommonSettings();
612 
613 #ifdef __WXMAC__
614  // Always show filters on Open dialog to be able to choose plugin
615  wxSystemOptions::SetOption( wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1 );
616 #endif
617 
618  return true;
619 }
620 
621 
623 {
624  m_bin_dir = wxStandardPaths::Get().GetExecutablePath();
625 
626 #ifdef __WXMAC__
627  // On OSX Pgm().GetExecutablePath() will always point to main
628  // bundle directory, e.g., /Applications/kicad.app/
629 
630  wxFileName fn( m_bin_dir );
631 
632  if( fn.GetName() == wxT( "kicad" ) )
633  {
634  // kicad launcher, so just remove the Contents/MacOS part
635  fn.RemoveLastDir();
636  fn.RemoveLastDir();
637  }
638  else
639  {
640  // standalone binaries live in Contents/Applications/<standalone>.app/Contents/MacOS
641  fn.RemoveLastDir();
642  fn.RemoveLastDir();
643  fn.RemoveLastDir();
644  fn.RemoveLastDir();
645  fn.RemoveLastDir();
646  }
647 
648  m_bin_dir = fn.GetPath() + wxT( "/" );
649 #else
650  // Use unix notation for paths. I am not sure this is a good idea,
651  // but it simplifies compatibility between Windows and Unices.
652  // However it is a potential problem in path handling under Windows.
653  m_bin_dir.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
654 
655  // Remove file name form command line:
656  while( m_bin_dir.Last() != '/' && !m_bin_dir.IsEmpty() )
657  m_bin_dir.RemoveLast();
658 #endif
659 
660  return true;
661 }
662 
663 
665 {
666  wxASSERT( m_common_settings );
667 
668  m_help_size.x = 500;
669  m_help_size.y = 400;
670  m_iconsScale = 1.0;
671 
672  // This only effect the first time KiCad is run. The user's setting will be used for all
673  // subsequent runs. Menu icons are off by default on OSX and on for all other platforms.
674 #if defined( __WXMAC__ )
675  m_useIconsInMenus = false;
676 #else
677  m_useIconsInMenus = true;
678 #endif
679 
680  m_common_settings->Read( showEnvVarWarningDialog, &m_show_env_var_dialog );
681  m_common_settings->Read( entryUseIconsInMenus, &m_useIconsInMenus, m_useIconsInMenus );
682 
683  m_editor_name = m_common_settings->Read( wxT( "Editor" ) );
684 
685  wxString entry, oldPath;
686  wxArrayString entries;
687  long index = 0L;
688 
689  oldPath = m_common_settings->GetPath();
690  m_common_settings->SetPath( pathEnvVariables );
691 
692  while( m_common_settings->GetNextEntry( entry, index ) )
693  {
694  wxLogTrace( traceEnvVars,
695  wxT( "Enumerating over entry %s, %ld." ), GetChars( entry ), index );
696  entries.Add( entry );
697  }
698 
699  for( unsigned i = 0; i < entries.GetCount(); i++ )
700  {
701  wxString val = m_common_settings->Read( entries[i], wxEmptyString );
702 
703  if( m_local_env_vars[ entries[i] ].GetDefinedExternally() )
704  continue;
705 
706  m_local_env_vars[ entries[i] ] = ENV_VAR_ITEM( val, wxGetEnv( entries[i], NULL ) );
707  }
708 
709  for( ENV_VAR_MAP_ITER it = m_local_env_vars.begin(); it != m_local_env_vars.end(); ++it )
710  SetLocalEnvVariable( it->first, it->second.GetValue() );
711 
712  m_common_settings->SetPath( oldPath );
713 }
714 
715 
717 {
718  // m_common_settings is not initialized until fairly late in the
719  // process startup: InitPgm(), so test before using:
720  if( m_common_settings )
721  {
722  wxString cur_dir = wxGetCwd();
723 
724  m_common_settings->Write( workingDirKey, cur_dir );
725  m_common_settings->Write( showEnvVarWarningDialog, m_show_env_var_dialog );
726  m_common_settings->Write( entryUseIconsInMenus, m_useIconsInMenus);
727 
728  // Save the local environment variables.
729  m_common_settings->SetPath( pathEnvVariables );
730 
731  for( ENV_VAR_MAP_ITER it = m_local_env_vars.begin(); it != m_local_env_vars.end(); ++it )
732  {
733  if( it->second.GetDefinedExternally() )
734  continue;
735 
736  wxLogTrace( traceEnvVars, wxT( "Saving environment variable config entry %s as %s" ),
737  GetChars( it->first ), GetChars( it->second.GetValue() ) );
738  m_common_settings->Write( it->first, it->second.GetValue() );
739  }
740 
741  m_common_settings->SetPath( wxT( ".." ) );
742  }
743 }
744 
745 
746 bool PGM_BASE::SetLanguage( bool first_time )
747 {
748  bool retv = true;
749 
750  if( first_time )
751  {
752  setLanguageId( wxLANGUAGE_DEFAULT );
753  // First time SetLanguage is called, the user selected language id is set
754  // from commun user config settings
755  wxString languageSel;
756 
757  m_common_settings->Read( languageCfgKey, &languageSel );
758 
759  // Search for the current selection
760  for( unsigned ii = 0; ii < DIM( s_Languages ); ii++ )
761  {
762  if( s_Languages[ii].m_Lang_Label == languageSel )
763  {
764  setLanguageId( s_Languages[ii].m_WX_Lang_Identifier );
765  break;
766  }
767  }
768  }
769 
770  // dictionary file name without extend (full name is kicad.mo)
771  wxString dictionaryName( wxT( "kicad" ) );
772 
773  delete m_locale;
774  m_locale = new wxLocale;
775 
776  if( !m_locale->Init( m_language_id ) )
777  {
778  wxLogDebug( wxT( "This language is not supported by the system." ) );
779 
780  setLanguageId( wxLANGUAGE_DEFAULT );
781  delete m_locale;
782 
783  m_locale = new wxLocale;
784  m_locale->Init();
785  retv = false;
786  }
787  else if( !first_time )
788  {
789  wxLogDebug( wxT( "Search for dictionary %s.mo in %s" ),
790  GetChars( dictionaryName ), GetChars( m_locale->GetName() ) );
791  }
792 
793  if( !first_time )
794  {
795  // If we are here, the user has selected another language.
796  // Therefore the new prefered language name is stored in common config.
797  // Do NOT store the wxWidgets language Id, it can change between wxWidgets
798  // versions, for a given language
799  wxString languageSel;
800 
801  // Search for the current selection language name
802  for( unsigned ii = 0; ii < DIM( s_Languages ); ii++ )
803  {
804  if( s_Languages[ii].m_WX_Lang_Identifier == m_language_id )
805  {
806  languageSel = s_Languages[ii].m_Lang_Label;
807  break;
808  }
809  }
810 
811  m_common_settings->Write( languageCfgKey, languageSel );
812  }
813 
814  // Test if floating point notation is working (bug encountered in cross compilation)
815  // Make a conversion double <=> string
816  double dtst = 0.5;
817  wxString msg;
818 
819  msg << dtst;
820  double result;
821  msg.ToDouble( &result );
822 
823  if( result != dtst )
824  // string to double encode/decode does not work! Bug detected:
825  // Disable floating point localization:
826  setlocale( LC_ALL, "C" );
827 
828  if( !m_locale->IsLoaded( dictionaryName ) )
829  m_locale->AddCatalog( dictionaryName );
830 
831  if( !retv )
832  return retv;
833 
834  return m_locale->IsOk();
835 }
836 
837 
839 {
840  wxLogDebug( wxT( "Select language ID %d from %d possible languages." ),
841  menu_id, DIM( s_Languages ) );
842 
843  for( unsigned ii = 0; ii < DIM( s_Languages ); ii++ )
844  {
845  if( menu_id == s_Languages[ii].m_KI_Lang_Identifier )
846  {
847  setLanguageId( s_Languages[ii].m_WX_Lang_Identifier );
848  break;
849  }
850  }
851 }
852 
853 
855 {
856  SEARCH_STACK guesses;
857 
858  SystemDirsAppend( &guesses );
859 
860  // Add our internat dir to the wxLocale catalog of paths
861  for( unsigned i = 0; i < guesses.GetCount(); i++ )
862  {
863  wxFileName fn( guesses[i], wxEmptyString );
864 
865  // Append path for Windows and unix KiCad package install
866  fn.AppendDir( wxT( "share" ) );
867  fn.AppendDir( wxT( "internat" ) );
868 
869  if( fn.IsDirReadable() )
870  {
871  wxLogDebug( wxT( "Adding locale lookup path: " ) + fn.GetPath() );
872  wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
873  }
874 
875  // Append path for unix standard install
876  fn.RemoveLastDir();
877  fn.AppendDir( wxT( "kicad" ) );
878  fn.AppendDir( wxT( "internat" ) );
879 
880  if( fn.IsDirReadable() )
881  {
882  wxLogDebug( wxT( "Adding locale lookup path: " ) + fn.GetPath() );
883  wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
884  }
885  }
886 }
887 
888 
889 void PGM_BASE::AddMenuLanguageList( wxMenu* MasterMenu )
890 {
891  wxMenu* menu = NULL;
892  wxMenuItem* item = MasterMenu->FindItem( ID_LANGUAGE_CHOICE );
893 
894  if( item ) // This menu exists, do nothing
895  return;
896 
897  menu = new wxMenu;
898 
899  for( unsigned ii = 0; ii < DIM( s_Languages ); ii++ )
900  {
901  wxString label;
902 
903  if( s_Languages[ii].m_DoNotTranslate )
904  label = s_Languages[ii].m_Lang_Label;
905  else
906  label = wxGetTranslation( s_Languages[ii].m_Lang_Label );
907 
908  AddMenuItem( menu, s_Languages[ii].m_KI_Lang_Identifier,
909  label, KiBitmap(s_Languages[ii].m_Lang_Icon ),
910  wxITEM_CHECK );
911  }
912 
913  AddMenuItem( MasterMenu, menu,
915  _( "Set Language" ),
916  _( "Select application language (only for testing)" ),
917  KiBitmap( language_xpm ) );
918 
919  // Set Check mark on current selected language
920  for( unsigned ii = 0; ii < DIM( s_Languages ); ii++ )
921  {
922  if( m_language_id == s_Languages[ii].m_WX_Lang_Identifier )
923  menu->Check( s_Languages[ii].m_KI_Lang_Identifier, true );
924  else
925  menu->Check( s_Languages[ii].m_KI_Lang_Identifier, false );
926  }
927 }
928 
929 
930 bool PGM_BASE::SetLocalEnvVariable( const wxString& aName, const wxString& aValue )
931 {
932  wxString env;
933 
934  // Check to see if the environment variable is already set.
935  if( wxGetEnv( aName, &env ) )
936  {
937  wxLogTrace( traceEnvVars, wxT( "Environment variable %s already set to %s." ),
938  GetChars( aName ), GetChars( env ) );
939  return env == aValue;
940  }
941 
942  wxLogTrace( traceEnvVars, wxT( "Setting local environment variable %s to %s." ),
943  GetChars( aName ), GetChars( aValue ) );
944 
945  return wxSetEnv( aName, aValue );
946 }
947 
948 
950 {
951  m_local_env_vars.clear();
952  m_local_env_vars = aEnvVarMap;
953 
954  if( m_common_settings )
955  m_common_settings->DeleteGroup( pathEnvVariables );
956 
957  SaveCommonSettings();
958 
959  // Overwrites externally defined environment variable until the next time the application
960  // is run.
961  for( ENV_VAR_MAP_ITER it = m_local_env_vars.begin(); it != m_local_env_vars.end(); ++it )
962  {
963  wxLogTrace( traceEnvVars, wxT( "Setting local environment variable %s to %s." ),
964  GetChars( it->first ), GetChars( it->second.GetValue() ) );
965  wxSetEnv( it->first, it->second.GetValue() );
966  }
967 }
968 
969 
970 void PGM_BASE::ConfigurePaths( wxWindow* aParent )
971 {
972  DIALOG_ENV_VAR_CONFIG dlg_envvars( aParent, GetLocalEnvVariables() );
973 
974  if( dlg_envvars.ShowModal() == wxID_CANCEL )
975  return;
976 
977  ENV_VAR_MAP envVarMap = dlg_envvars.GetEnvVarMap();
978 
979  for( ENV_VAR_MAP_ITER it = envVarMap.begin(); it != envVarMap.end(); ++it )
980  {
981  wxLogTrace( traceEnvVars, wxT( "Environment variable %s=%s defined externally = %d" ),
982  GetChars( it->first ), GetChars( it->second.GetValue() ),
983  it->second.GetDefinedExternally() );
984  }
985 
986  // If any of the environment variables are defined externally, warn the user that the
987  // next time kicad is run that the externally defined variables will be used instead of
988  // the user's settings. This is by design.
989  if( dlg_envvars.ExternalDefsChanged() && m_show_env_var_dialog )
990  {
991  wxString msg1 = _( "Warning! Some of paths you have configured have been defined \n"
992  "externally to the running process and will be temporarily overwritten." );
993  wxString msg2 = _( "The next time KiCad is launched, any paths that have already\n"
994  "been defined are honored and any settings defined in the path\n"
995  "configuration dialog are ignored. If you did not intend for this\n"
996  "behavior, either rename any conflicting entries or remove the\n"
997  "external environment variable definition(s) from your system." );
998  wxRichMessageDialog dlg( aParent, msg1, _( "Warning" ), wxOK | wxCENTRE );
999  dlg.ShowDetailedText( msg2 );
1000  dlg.ShowCheckBox( _( "Do not show this message again." ) );
1001  dlg.ShowModal();
1002  m_show_env_var_dialog = !dlg.IsCheckBoxChecked();
1003  }
1004 
1005  SetLocalEnvVariables( dlg_envvars.GetEnvVarMap() );
1006 }
static const wxChar pathEnvVariables[]
Definition: pgm_base.cpp:65
void loadCommonSettings()
Function loadCommonSettings loads the program (process) settings subset which are stored in ...
Definition: pgm_base.cpp:664
#define DIM(x)
of elements in an array
Definition: macros.h:98
wxString GetKicadLockFilePath()
Function GetKicadLockFilePath.
Definition: lockfile.cpp:59
#define WIN_STRING_DIR_SEP
Definition: gestfich.h:44
VTBL_ENTRY void SetEditorName(const wxString &aFileName)
Definition: pgm_base.cpp:330
virtual ~PGM_BASE()
Definition: pgm_base.cpp:302
PNG memory record (file in memory).
Definition: bitmap_types.h:41
This file is part of the common library TODO brief description.
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:716
wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmap &aImage, wxItemKind aType=wxITEM_NORMAL)
Function AddMenuItem is an inline helper function to create and insert a menu item with an icon into ...
Definition: bitmap.cpp:174
#define UNIX_STRING_DIR_SEP
Definition: gestfich.h:43
Class ENV_VAR_ITEM.
Definition: pgm_base.h:58
static const wxChar workingDirKey[]
Definition: pgm_base.h:297
BITMAP_DEF m_Lang_Icon
The menu language icons.
Definition: pgm_base.cpp:89
static const wxChar showEnvVarWarningDialog[]
Definition: pgm_base.cpp:66
int m_KI_Lang_Identifier
KiCad identifier used in menu selection (See id.h)
Definition: pgm_base.cpp:86
wxConfigBase * GetNewConfig(const wxString &aProgName)
Create a new wxConfig so we can put configuration files in a more proper place for each platform...
Definition: common.cpp:199
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:323
static const wxChar traceEnvVars[]
enable/disable icons in menus
Definition: pgm_base.cpp:67
void Destroy()
Definition: pgm_base.cpp:308
bool setExecutablePath()
Function setExecutablePath finds the path to the executable and stores it in PGM_BASE::m_bin_dir.
Definition: pgm_base.cpp:622
System directories search utilities.
The common library.
A small class to handle the list of existing translations.
Definition: pgm_base.cpp:80
static const wxChar entryUseIconsInMenus[]
Definition: pgm_base.cpp:69
Class SEARCH_STACK looks for files in a number of places.
Definition: search_stack.h:41
bool m_DoNotTranslate
Set to true if the m_Lang_Label must not be translated.
Definition: pgm_base.cpp:95
VTBL_ENTRY const wxString AskUserForPreferredEditor(const wxString &aDefaultEditor=wxEmptyString)
Shows a dialog that instructs the user to select a new preferred editor.
Definition: pgm_base.cpp:375
#define KICAD_COMMON
Definition: pgm_base.cpp:58
This file contains miscellaneous commonly used macros and functions.
VTBL_ENTRY void ConfigurePaths(wxWindow *aParent=NULL)
Function ConfigurePaths.
Definition: pgm_base.cpp:970
wxBitmap KiBitmap(BITMAP_DEF aBitmap)
Function KiBitmap constructs a wxBitmap from a memory record, held in a BITMAP_DEF.
Definition: bitmap.cpp:78
VTBL_ENTRY bool SetLocalEnvVariable(const wxString &aName, const wxString &aValue)
Function SetLocalEnvVariable.
Definition: pgm_base.cpp:930
const ENV_VAR_MAP & GetEnvVarMap() const
VTBL_ENTRY void SetLanguageIdentifier(int menu_id)
Function SetLanguageIdentifier sets in .m_language_id member the wxWidgets language identifier Id fro...
Definition: pgm_base.cpp:838
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
Definition: pgm_base.h:87
void SetDefinedExternally(bool aIsDefinedExternally)
Definition: pgm_base.h:70
wxString EDA_FILE_SELECTOR(const wxString &aTitle, const wxString &aPath, const wxString &aFileName, const wxString &aExtension, const wxString &aWildcard, wxWindow *aParent, int aStyle, const bool aKeepWorkingDirectory, const wxPoint &aPosition, wxString *aMruPath)
Function EDA_FILE_SELECTOR.
Definition: gestfich.cpp:82
Base window classes and related definitions.
void SystemDirsAppend(SEARCH_STACK *aSearchStack)
Function SystemDirsAppend appends system places to aSearchStack in a platform specific way...
DIALOG_ENV_VAR_CONFIG class declaration.
int m_WX_Lang_Identifier
wxWidgets locale identifier (See wxWidgets doc)
Definition: pgm_base.cpp:83
wxString m_Lang_Label
Labels used in menus.
Definition: pgm_base.cpp:92
VTBL_ENTRY void SetLanguagePath()
Definition: pgm_base.cpp:854
VTBL_ENTRY bool SetLanguage(bool first_time=false)
Function SetLanguage sets the dictionary file name for internationalization.
Definition: pgm_base.cpp:746
VTBL_ENTRY void SetLocalEnvVariables(const ENV_VAR_MAP &aEnvVarMap)
Function SetLocalEnvVariables.
Definition: pgm_base.cpp:949
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
const char * name
Definition: DXF_plotter.cpp:61
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
void SetValue(const wxString &aValue)
Definition: pgm_base.h:76
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:398
static const wxChar languageCfgKey[]
Definition: pgm_base.cpp:64
static LANGUAGE_DESCR s_Languages[]
Variable s_Languages Note: because this list is not created on the fly, wxTranslation must be called ...
Definition: pgm_base.cpp:105
std::map< wxString, ENV_VAR_ITEM >::iterator ENV_VAR_MAP_ITER
Definition: pgm_base.h:88
VTBL_ENTRY const wxString & GetEditorName(bool aCanShowFileChooser=true)
Return the preferred editor name.
Definition: pgm_base.cpp:338
VTBL_ENTRY void AddMenuLanguageList(wxMenu *MasterMenu)
Function AddMenuLanguageList creates a menu list for language choice, and add it as submenu to Master...
Definition: pgm_base.cpp:889
Some functions to handle hotkeys in KiCad.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Function DisplayInfoMessage displays an informational message box with aMessage.
Definition: confirm.cpp:216
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Function IsOK displays a yes/no dialog with aMessage and returns the user response.
Definition: confirm.cpp:233
void AddPaths(const wxString &aPaths, int aIndex=-1)
Function AddPaths insert or append path(s)
File locking utilities.