KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 <[email protected]>
6 * Copyright The 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
32
33#include <wx/html/htmlwin.h>
34#include <wx/fs_zip.h>
35#include <wx/dir.h>
36#include <wx/filename.h>
37#include <wx/msgdlg.h>
38#include <wx/propgrid/propgrid.h>
39#include <wx/snglinst.h>
40#include <wx/stdpaths.h>
41#include <wx/sysopt.h>
42#include <wx/filedlg.h>
43#include <wx/ffile.h>
44#include <wx/tooltip.h>
45
46#include <advanced_config.h>
47#include <app_monitor.h>
49#include <bitmaps.h>
50#include <build_version.h>
51#include <common.h>
52#include <confirm.h>
53#include <core/arraydim.h>
54#include <id.h>
56#include <kiplatform/policy.h>
58#include <macros.h>
60#include <paths.h>
61#include <pgm_base.h>
63#include <policy_keys.h>
64#include <python_scripting.h>
67#include <string_utils.h>
68#include <systemdirsappend.h>
69#include <thread_pool.h>
70#include <trace_helpers.h>
71
72#include <widgets/wx_splash.h>
73
74#ifdef KICAD_IPC_API
76#include <api/api_server.h>
77#include <python_manager.h>
78#endif
79
80#ifdef _MSC_VER
81#include <winrt/base.h>
82#endif
92#undef _
93#define _(s) s
95{
96 { wxLANGUAGE_DEFAULT, ID_LANGUAGE_DEFAULT, _( "Default" ), false },
97 { wxLANGUAGE_ARABIC, ID_LANGUAGE_ARABIC, wxT( "العربية" ), true },
98 { wxLANGUAGE_INDONESIAN, ID_LANGUAGE_INDONESIAN, wxT( "Bahasa Indonesia" ), true },
99 { wxLANGUAGE_BULGARIAN, ID_LANGUAGE_BULGARIAN, wxT( "Български" ), true },
100 { wxLANGUAGE_CATALAN, ID_LANGUAGE_CATALAN, wxT( "Català" ), true },
101 { wxLANGUAGE_CZECH, ID_LANGUAGE_CZECH, wxT( "Čeština" ), true },
102 { wxLANGUAGE_DANISH, ID_LANGUAGE_DANISH, wxT( "Dansk" ), true },
103 { wxLANGUAGE_GERMAN, ID_LANGUAGE_GERMAN, wxT( "Deutsch" ), true },
104 { wxLANGUAGE_GREEK, ID_LANGUAGE_GREEK, wxT( "Ελληνικά" ), true },
105 { wxLANGUAGE_ENGLISH, ID_LANGUAGE_ENGLISH, wxT( "English" ), true },
106 { wxLANGUAGE_SPANISH, ID_LANGUAGE_SPANISH, wxT( "Español" ), true },
107 { wxLANGUAGE_SPANISH_MEXICAN, ID_LANGUAGE_SPANISH_MEXICAN,
108 wxT( "Español (Latinoamericano)" ), true },
109 { wxLANGUAGE_FRENCH, ID_LANGUAGE_FRENCH, wxT( "Français" ), true },
110 { wxLANGUAGE_HEBREW, ID_LANGUAGE_HEBREW, wxT( "עברית" ), true },
111 { wxLANGUAGE_KOREAN, ID_LANGUAGE_KOREAN, wxT( "한국어"), true },
112 { wxLANGUAGE_ITALIAN, ID_LANGUAGE_ITALIAN, wxT( "Italiano" ), true },
113 { wxLANGUAGE_LATVIAN, ID_LANGUAGE_LATVIAN, wxT( "Latviešu" ), true },
114 { wxLANGUAGE_LITHUANIAN, ID_LANGUAGE_LITHUANIAN, wxT( "Lietuvių" ), true },
115 { wxLANGUAGE_HUNGARIAN, ID_LANGUAGE_HUNGARIAN, wxT( "Magyar" ), true },
116 { wxLANGUAGE_DUTCH, ID_LANGUAGE_DUTCH, wxT( "Nederlands" ), true },
117 { wxLANGUAGE_NORWEGIAN_BOKMAL, ID_LANGUAGE_NORWEGIAN_BOKMAL, wxT( "Norsk Bokmål" ), true },
118 { wxLANGUAGE_JAPANESE, ID_LANGUAGE_JAPANESE, wxT( "日本語" ), true },
119 { wxLANGUAGE_THAI, ID_LANGUAGE_THAI, wxT( "ภาษาไทย" ), true },
120 { wxLANGUAGE_POLISH, ID_LANGUAGE_POLISH, wxT( "Polski" ), true },
121 { wxLANGUAGE_PORTUGUESE, ID_LANGUAGE_PORTUGUESE, wxT( "Português" ),true },
122 { wxLANGUAGE_PORTUGUESE_BRAZILIAN, ID_LANGUAGE_PORTUGUESE_BRAZILIAN,
123 wxT( "Português (Brasil)" ), true },
124 { wxLANGUAGE_ROMANIAN, ID_LANGUAGE_ROMANIAN, wxT( "Română" ), true },
125 { wxLANGUAGE_RUSSIAN, ID_LANGUAGE_RUSSIAN, wxT( "Русский" ), true },
126 { wxLANGUAGE_SERBIAN, ID_LANGUAGE_SERBIAN, wxT( "Српски" ), true },
127 { wxLANGUAGE_SLOVAK, ID_LANGUAGE_SLOVAK, wxT( "Slovenčina" ), true },
128 { wxLANGUAGE_SLOVENIAN, ID_LANGUAGE_SLOVENIAN, wxT( "Slovenščina" ), true },
129 { wxLANGUAGE_FINNISH, ID_LANGUAGE_FINNISH, wxT( "Suomi" ), true },
130 { wxLANGUAGE_SWEDISH, ID_LANGUAGE_SWEDISH, wxT( "Svenska" ), true },
131 { wxLANGUAGE_VIETNAMESE, ID_LANGUAGE_VIETNAMESE, wxT( "Tiếng Việt" ), true },
132 { wxLANGUAGE_TAMIL, ID_LANGUAGE_TAMIL, wxT( "தமிழ்" ), true },
133 { wxLANGUAGE_TURKISH, ID_LANGUAGE_TURKISH, wxT( "Türkçe" ), true },
134 { wxLANGUAGE_UKRAINIAN, ID_LANGUAGE_UKRAINIAN, wxT( "Українська" ), true },
135 { wxLANGUAGE_CHINESE_SIMPLIFIED, ID_LANGUAGE_CHINESE_SIMPLIFIED,
136 wxT( "简体中文" ), true },
137 { wxLANGUAGE_CHINESE_TRADITIONAL, ID_LANGUAGE_CHINESE_TRADITIONAL,
138 wxT( "繁體中文" ), true },
139 { 0, 0, "", false } // Sentinel
140};
141#undef _
142#define _(s) wxGetTranslation((s))
143
144
146{
147 m_locale = nullptr;
148 m_Printing = false;
149 m_Quitting = false;
150 m_argcUtf8 = 0;
151 m_argvUtf8 = nullptr;
152 m_splash = nullptr;
154
155 setLanguageId( wxLANGUAGE_DEFAULT );
156
157 ForceSystemPdfBrowser( false );
158}
159
160
162{
163 HideSplash();
164 Destroy();
165
166 for( int n = 0; n < m_argcUtf8; n++ )
167 {
168 free( m_argvUtf8[n] );
169 }
170
171 delete[] m_argvUtf8;
172
173 delete m_locale;
174 m_locale = nullptr;
175}
176
177
179{
181
183
184 m_pgm_checker.reset();
185
186#ifdef _MSC_VER
187 winrt::uninit_apartment();
188#endif
189}
190
191
193{
194 wxASSERT( wxTheApp );
195 return *wxTheApp;
196}
197
198
199void PGM_BASE::SetTextEditor( const wxString& aFileName )
200{
201 m_text_editor = aFileName;
203}
204
205
206const wxString& PGM_BASE::GetTextEditor( bool aCanShowFileChooser )
207{
208 wxString editorname = m_text_editor;
209
210 if( !editorname )
211 {
212 if( !wxGetEnv( wxT( "EDITOR" ), &editorname ) )
213 {
214 // If there is no EDITOR variable set, try the desktop default
215#ifdef __WXMAC__
216 editorname = wxT( "/usr/bin/open -e" );
217#elif __WXX11__
218 editorname = wxT( "/usr/bin/xdg-open" );
219#endif
220 }
221 }
222
223 // If we still don't have an editor name show a dialog asking the user to select one
224 if( !editorname && aCanShowFileChooser )
225 {
226 DisplayInfoMessage( nullptr, _( "No default editor found, you must choose one." ) );
227
228 editorname = AskUserForPreferredEditor();
229 }
230
231 // If we finally have a new editor name request it to be copied to m_text_editor and
232 // saved to the preferences file.
233 if( !editorname.IsEmpty() )
234 SetTextEditor( editorname );
235
236 // m_text_editor already has the same value that editorname, or empty if no editor was
237 // found/chosen.
238 return m_text_editor;
239}
240
241
242const wxString PGM_BASE::AskUserForPreferredEditor( const wxString& aDefaultEditor )
243{
244 // Create a mask representing the executable files in the current platform
245#ifdef __WINDOWS__
246 wxString mask( _( "Executable file" ) + wxT( " (*.exe)|*.exe" ) );
247#else
248 wxString mask( _( "Executable file" ) + wxT( " (*)|*" ) );
249#endif
250
251 // Extract the path, name and extension from the default editor (even if the editor's
252 // name was empty, this method will succeed and return empty strings).
253 wxString path, name, ext;
254 wxFileName::SplitPath( aDefaultEditor, &path, &name, &ext );
255
256 // Show the modal editor and return the file chosen (may be empty if the user cancels
257 // the dialog).
258 return wxFileSelector( _( "Select Preferred Editor" ), path, name, wxT( "." ) + ext,
259 mask, wxFD_OPEN | wxFD_FILE_MUST_EXIST, nullptr );
260}
261
262
264{
265 const wxArrayString& argArray = App().argv.GetArguments();
266 m_argcUtf8 = argArray.size();
267
268 m_argvUtf8 = new char*[m_argcUtf8 + 1];
269 for( int n = 0; n < m_argcUtf8; n++ )
270 {
271 m_argvUtf8[n] = wxStrdup( argArray[n].ToUTF8() );
272 }
273
274 m_argvUtf8[m_argcUtf8] = NULL; // null terminator at end of argv
275}
276
277
279{
280 // Disabling until we change to load each DSO at startup rather than lazy-load when needed.
281 // Note that once the splash screen is re-enabled, there are some remaining bugs to fix:
282 // Any wxWidgets error dialogs that appear during startup are hidden by the splash screen,
283 // so we either need to prevent these from happening (probably not feasible) or else change
284 // the error-handling path to make sure errors go on top of the splash.
285#if 0
286 if( m_splash )
287 return;
288
289 m_splash = new WX_SPLASH( KiBitmap( BITMAPS::splash ), wxSPLASH_CENTRE_ON_SCREEN, 0,
290 NULL, -1, wxDefaultPosition, wxDefaultSize,
291 wxBORDER_NONE | wxSTAY_ON_TOP );
292 wxYield();
293#endif
294}
295
296
298{
299 if( !m_splash )
300 return;
301
302 m_splash->Close( true );
303 m_splash->Destroy();
304 m_splash = nullptr;
305}
306
307
308bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
309{
310#if defined( __WXMAC__ )
311 // Set the application locale to the system default
312 wxLogNull noLog;
313 wxLocale loc;
314 loc.Init();
315#endif
316
317 // Just make sure we init precreate any folders early for later code
318 // In particular, the user cache path is the most likely to be hit by startup code
320
322
324
325 // Initialize the singleton instance
326 m_singleton.Init();
327
328 wxString pgm_name;
329
331 if( App().argc == 0 )
332 pgm_name = wxT( "kicad" );
333 else
334 pgm_name = wxFileName( App().argv[0] ).GetName().Lower();
335
336 APP_MONITOR::SENTRY::Instance()->AddTag( "kicad.app", pgm_name );
337
338 wxInitAllImageHandlers();
339
340 // Without this the wxPropertyGridManager segfaults on Windows.
341 if( !wxPGGlobalVars )
342 wxPGInitResourceModule();
343
344#ifndef __WINDOWS__
345 if( wxString( wxGetenv( "HOME" ) ).IsEmpty() )
346 {
347 DisplayErrorMessage( nullptr, _( "Environment variable HOME is empty. "
348 "Unable to continue." ) );
349 return false;
350 }
351#endif
352
353 // Ensure the instance checker directory exists
354 // It should be globally writable because it is shared between all users on Linux, and so on a
355 // multi-user machine, other need to be able to access it to check for the lock files or make
356 // their own lock files.
357 wxString instanceCheckerDir = PATHS::GetInstanceCheckerPath();
358 PATHS::EnsurePathExists( instanceCheckerDir );
359 wxChmod( instanceCheckerDir,
360 wxPOSIX_USER_READ | wxPOSIX_USER_WRITE | wxPOSIX_USER_EXECUTE |
361 wxPOSIX_GROUP_READ | wxPOSIX_GROUP_WRITE | wxPOSIX_GROUP_EXECUTE |
362 wxPOSIX_OTHERS_READ | wxPOSIX_OTHERS_WRITE | wxPOSIX_OTHERS_EXECUTE );
363
364 wxString instanceCheckerName = wxString::Format( wxS( "%s-%s" ), pgm_name,
366
367 m_pgm_checker = std::make_unique<wxSingleInstanceChecker>();
368 m_pgm_checker->Create( instanceCheckerName, instanceCheckerDir );
369
370 // Init KiCad environment
371 // the environment variable KICAD (if exists) gives the kicad path:
372 // something like set KICAD=d:\kicad
373 bool isDefined = wxGetEnv( wxT( "KICAD" ), &m_kicad_env );
374
375 if( isDefined ) // ensure m_kicad_env ends by "/"
376 {
378
379 if( !m_kicad_env.IsEmpty() && m_kicad_env.Last() != '/' )
381 }
382
383 // Init parameters for configuration
384 App().SetVendorName( wxT( "KiCad" ) );
385 App().SetAppName( pgm_name );
386
387 // Install some image handlers, mainly for help
388 if( wxImage::FindHandler( wxBITMAP_TYPE_PNG ) == nullptr )
389 wxImage::AddHandler( new wxPNGHandler );
390
391 if( wxImage::FindHandler( wxBITMAP_TYPE_GIF ) == nullptr )
392 wxImage::AddHandler( new wxGIFHandler );
393
394 if( wxImage::FindHandler( wxBITMAP_TYPE_JPEG ) == nullptr )
395 wxImage::AddHandler( new wxJPEGHandler );
396
397 wxFileSystem::AddHandler( new wxZipFSHandler );
398
399 // Analyze the command line & initialize the binary path
400 wxString tmp;
402 SetDefaultLanguage( tmp );
403
404#ifdef _MSC_VER
405 if( !wxGetEnv( "FONTCONFIG_PATH", NULL ) )
406 {
407 // We need to set this because the internal fontconfig logic
408 // seems to search relative to the dll rather the other logic it
409 // has to look for the /etc folder above the dll
410 // Also don't set it because we need it in QA cli tests to be set by ctest
411 wxSetEnv( "FONTCONFIG_PATH", PATHS::GetWindowsFontConfigDir() );
412 }
413#endif
414
415#ifdef _MSC_VER
416 winrt::init_apartment(winrt::apartment_type::single_threaded);
417#endif
418
419 m_settings_manager = std::make_unique<SETTINGS_MANAGER>();
420 m_library_manager = std::make_unique<LIBRARY_MANAGER>();
421 m_background_jobs_monitor = std::make_unique<BACKGROUND_JOBS_MONITOR>();
422 m_notifications_manager = std::make_unique<NOTIFICATIONS_MANAGER>();
423
424#ifdef KICAD_IPC_API
425 m_plugin_manager = std::make_unique<API_PLUGIN_MANAGER>( &App() );
426#endif
427
428 // Our unit test mocks break if we continue
429 // A bug caused InitPgm to terminate early in unit tests and the mocks are...simplistic
430 // TODO fix the unit tests so this can be removed
431 if( aIsUnitTest )
432 return false;
433
434 // Something got in the way of settings load: can't continue
435 if( !m_settings_manager->IsOK() )
436 return false;
437
438 // Set up built-in environment variables (and override them from the system environment if set)
439 COMMON_SETTINGS* commonSettings = GetCommonSettings();
440 commonSettings->InitializeEnvironment();
441
442 // Load color settings after env is initialized
443 m_settings_manager->ReloadColorSettings();
444
445 // Load common settings from disk after setting up env vars
446 GetSettingsManager().Load( commonSettings );
447
448#ifdef KICAD_IPC_API
449 // If user doesn't have a saved Python interpreter, try (potentially again) to find one
450 if( commonSettings->m_Api.python_interpreter.IsEmpty() )
451 commonSettings->m_Api.python_interpreter = PYTHON_MANAGER::FindPythonInterpreter();
452#endif
453
454 // Init user language *before* calling loadSettings, because
455 // env vars could be incorrectly initialized on Linux
456 // (if the value contains some non ASCII7 chars, the env var is not initialized)
457 SetLanguage( tmp, true );
458
459 // Now that translations are available, inform the user if the OS is unsupported
461
463
464 ReadPdfBrowserInfos(); // needs GetCommonSettings()
465
467
468 // Create the python scripting stuff
469 // Skip it for applications that do not use it
470 if( !aSkipPyInit )
471 m_python_scripting = std::make_unique<SCRIPTING>();
472
473 // TODO(JE): Remove this if apps are refactored to not assume Prj() always works
474 // Need to create a project early for now (it can have an empty path for the moment)
476
477#ifdef KICAD_IPC_API
478 if( commonSettings->m_Api.enable_server )
479 m_plugin_manager->ReloadPlugins();
480#endif
481
482 // This sets the maximum tooltip display duration to 10s (up from 5) but only affects
483 // Windows as other platforms display tooltips while the mouse is not moving
484 if( !aHeadless )
485 {
486 wxToolTip::Enable( true );
487 wxToolTip::SetAutoPop( 10000 );
488 }
489
490 if( ADVANCED_CFG::GetCfg().m_UpdateUIEventInterval != 0 )
491 wxUpdateUIEvent::SetUpdateInterval( ADVANCED_CFG::GetCfg().m_UpdateUIEventInterval );
492
493 // Now the application can safely start, show the splash screen
494 if( !aHeadless )
495 ShowSplash();
496
497 return true;
498}
499
500
502{
504
505 for( const std::pair<wxString, ENV_VAR_ITEM> it : GetCommonSettings()->m_Env.vars )
506 {
507 wxLogTrace( traceEnvVars, wxT( "PGM_BASE::loadSettings: Found entry %s = %s" ),
508 it.first, it.second.GetValue() );
509
510 // Do not store the env var PROJECT_VAR_NAME ("KIPRJMOD") definition if for some reason
511 // it is found in config. (It is reserved and defined as project path)
512 if( it.first == PROJECT_VAR_NAME )
513 continue;
514
515 // Don't set bogus empty entries in the environment
516 if( it.first.IsEmpty() )
517 continue;
518
519 // Do not overwrite vars set by the system environment with values from the settings file
520 if( it.second.GetDefinedExternally() )
521 continue;
522
523 SetLocalEnvVariable( it.first, it.second.GetValue() );
524 }
525}
526
527
529{
530 // GetCommonSettings() is not initialized until fairly late in the
531 // process startup: InitPgm(), so test before using:
532 if( GetCommonSettings() )
533 GetCommonSettings()->m_System.working_dir = wxGetCwd();
534}
535
536
538{
539 return m_settings_manager ? m_settings_manager->GetCommonSettings() : nullptr;
540}
541
542
543bool PGM_BASE::SetLanguage( wxString& aErrMsg, bool first_time )
544{
545 // Suppress wxWidgets error popups if locale is not found
546 wxLogNull doNotLog;
547
548 if( first_time )
549 {
550 setLanguageId( wxLANGUAGE_DEFAULT );
551
552 // First time SetLanguage is called, the user selected language id is set
553 // from common user config settings
554 wxString languageSel = GetCommonSettings()->m_System.language;
555
556 // Search for the current selection
557 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
558 {
559 if( LanguagesList[ii].m_Lang_Label == languageSel )
560 {
561 setLanguageId( LanguagesList[ii].m_WX_Lang_Identifier );
562 break;
563 }
564 }
565 }
566
567 // dictionary file name without extend (full name is kicad.mo)
568 wxString dictionaryName( wxT( "kicad" ) );
569
570 delete m_locale;
571 m_locale = new wxLocale;
572
573 // don't use wxLOCALE_LOAD_DEFAULT flag so that Init() doesn't return
574 // false just because it failed to load wxstd catalog
575 if( !m_locale->Init( m_language_id ) )
576 {
577 wxLogTrace( traceLocale, wxT( "This language is not supported by the system." ) );
578
579 setLanguageId( wxLANGUAGE_DEFAULT );
580 delete m_locale;
581
582 m_locale = new wxLocale;
583 m_locale->Init( wxLANGUAGE_DEFAULT );
584
585 aErrMsg = _( "This language is not supported by the operating system." );
586 return false;
587 }
588 else if( !first_time )
589 {
590 wxLogTrace( traceLocale, wxT( "Search for dictionary %s.mo in %s" ) ,
591 dictionaryName, m_locale->GetName() );
592 }
593
594 if( !first_time )
595 {
596 // If we are here, the user has selected another language.
597 // Therefore the new preferred language name is stored in common config.
598 // Do NOT store the wxWidgets language Id, it can change between wxWidgets
599 // versions, for a given language
600 wxString languageSel;
601
602 // Search for the current selection language name
603 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
604 {
605 if( LanguagesList[ii].m_WX_Lang_Identifier == m_language_id )
606 {
607 languageSel = LanguagesList[ii].m_Lang_Label;
608 break;
609 }
610 }
611
613 cfg->m_System.language = languageSel;
614 cfg->SaveToFile( GetSettingsManager().GetPathForSettingsFile( cfg ) );
615 }
616
617 // Try adding the dictionary if it is not currently loaded
618 if( !m_locale->IsLoaded( dictionaryName ) )
619 m_locale->AddCatalog( dictionaryName );
620
621 // Verify the Kicad dictionary was loaded properly
622 // However, for the English language, the dictionary is not mandatory, as
623 // all messages are already in English, just restricted to ASCII7 chars,
624 // the verification is skipped.
625 if( !m_locale->IsLoaded( dictionaryName ) && m_language_id != wxLANGUAGE_ENGLISH )
626 {
627 wxLogTrace( traceLocale, wxT( "Unable to load dictionary %s.mo in %s" ),
628 dictionaryName, m_locale->GetName() );
629
630 setLanguageId( wxLANGUAGE_DEFAULT );
631 delete m_locale;
632
633 m_locale = new wxLocale;
634 m_locale->Init( wxLANGUAGE_DEFAULT );
635
636 aErrMsg = _( "The KiCad language file for this language is not installed." );
637 return false;
638 }
639
640 return true;
641}
642
643
644bool PGM_BASE::SetDefaultLanguage( wxString& aErrMsg )
645{
646 // Suppress error popups from wxLocale
647 wxLogNull doNotLog;
648
649 setLanguageId( wxLANGUAGE_DEFAULT );
650
651 // dictionary file name without extend (full name is kicad.mo)
652 wxString dictionaryName( wxT( "kicad" ) );
653
654 delete m_locale;
655 m_locale = new wxLocale;
656 m_locale->Init();
657
658 // Try adding the dictionary if it is not currently loaded
659 if( !m_locale->IsLoaded( dictionaryName ) )
660 m_locale->AddCatalog( dictionaryName );
661
662 // Verify the Kicad dictionary was loaded properly
663 // However, for the English language, the dictionary is not mandatory, as
664 // all messages are already in English, just restricted to ASCII7 chars,
665 // the verification is skipped.
666 if( !m_locale->IsLoaded( dictionaryName ) && m_language_id != wxLANGUAGE_ENGLISH )
667 {
668 wxLogTrace( traceLocale, wxT( "Unable to load dictionary %s.mo in %s" ),
669 dictionaryName, m_locale->GetName() );
670
671 setLanguageId( wxLANGUAGE_DEFAULT );
672 delete m_locale;
673
674 m_locale = new wxLocale;
675 m_locale->Init();
676
677 aErrMsg = _( "The KiCad language file for this language is not installed." );
678 return false;
679 }
680
681 return true;
682}
683
684
686{
687 wxLogTrace( traceLocale, wxT( "Select language ID %d from %d possible languages." ),
688 menu_id, (int)arrayDim( LanguagesList )-1 );
689
690 for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
691 {
692 if( menu_id == LanguagesList[ii].m_KI_Lang_Identifier )
693 {
694 setLanguageId( LanguagesList[ii].m_WX_Lang_Identifier );
695 break;
696 }
697 }
698}
699
700
702{
703 const wxLanguageInfo* langInfo = wxLocale::GetLanguageInfo( m_language_id );
704
705 if( !langInfo )
706 {
707 return "";
708 }
709 else
710 {
711 wxString str = langInfo->GetCanonicalWithRegion();
712 str.Replace( "_", "-" );
713
714 return str;
715 }
716}
717
718
720{
721#ifdef _MSC_VER
722 wxLocale::AddCatalogLookupPathPrefix( PATHS::GetWindowsBaseSharePath() + wxT( "locale" ) );
723#endif
724 wxLocale::AddCatalogLookupPathPrefix( PATHS::GetLocaleDataPath() );
725
726 if( wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) )
727 {
728 wxFileName fn( Pgm().GetExecutablePath() );
729 fn.RemoveLastDir();
730 fn.AppendDir( wxT( "translation" ) );
731 wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
732 }
733}
734
735
736bool PGM_BASE::SetLocalEnvVariable( const wxString& aName, const wxString& aValue )
737{
738 wxString env;
739
740 if( aName.IsEmpty() )
741 {
742 wxLogTrace( traceEnvVars,
743 wxT( "PGM_BASE::SetLocalEnvVariable: Attempt to set empty variable to "
744 "value %s" ),
745 aValue );
746 return false;
747 }
748
749 // Check to see if the environment variable is already set.
750 if( wxGetEnv( aName, &env ) )
751 {
752 wxLogTrace( traceEnvVars,
753 wxT( "PGM_BASE::SetLocalEnvVariable: Environment variable %s already set "
754 "to %s" ),
755 aName, env );
756 return env == aValue;
757 }
758
759 wxLogTrace( traceEnvVars,
760 wxT( "PGM_BASE::SetLocalEnvVariable: Setting local environment variable %s to %s" ),
761 aName, aValue );
762
763 return wxSetEnv( aName, aValue );
764}
765
766
768{
769 // Overwrites externally defined environment variable until the next time the application
770 // is run.
771 for( const std::pair<wxString, ENV_VAR_ITEM> m_local_env_var : GetCommonSettings()->m_Env.vars )
772 {
773 wxLogTrace( traceEnvVars,
774 wxT( "PGM_BASE::SetLocalEnvVariables: Setting local environment variable %s "
775 "to %s" ),
776 m_local_env_var.first,
777 m_local_env_var.second.GetValue() );
778 wxSetEnv( m_local_env_var.first, m_local_env_var.second.GetValue() );
779 }
780}
781
782
787
788
790{
791 if( !wxTheApp )
792 return false;
793
794 return wxTheApp->IsGUI();
795}
796
797
798void PGM_BASE::HandleException( std::exception_ptr aPtr )
799{
800 try
801 {
802 if( aPtr )
803 std::rethrow_exception( aPtr );
804 }
805 catch( const IO_ERROR& ioe )
806 {
807 wxLogError( ioe.What() );
808 }
809 catch( const std::exception& e )
810 {
812
813 wxLogError( wxT( "Unhandled exception class: %s what: %s" ),
814 From_UTF8( typeid( e ).name() ), From_UTF8( e.what() ) );
815 }
816 catch( ... )
817 {
818 wxLogError( wxT( "Unhandled exception of unknown type" ) );
819 }
820}
821
822
823void PGM_BASE::HandleAssert( const wxString& aFile, int aLine, const wxString& aFunc,
824 const wxString& aCond, const wxString& aMsg )
825{
826 wxString assertStr;
827
828 // Log the assertion details to standard log
829 if( !aMsg.empty() )
830 {
831 assertStr = wxString::Format( "Assertion failed at %s:%d in %s: %s - %s", aFile, aLine,
832 aFunc, aCond, aMsg );
833 }
834 else
835 {
836 assertStr = wxString::Format( "Assertion failed at %s:%d in %s: %s", aFile, aLine, aFunc,
837 aCond );
838 }
839
840#ifndef NDEBUG
841 wxLogError( assertStr );
842#endif
843
844#ifdef KICAD_USE_SENTRY
845 APP_MONITOR::ASSERT_CACHE_KEY key = { aFile, aLine, aFunc, aCond };
846 APP_MONITOR::SENTRY::Instance()->LogAssert( key, assertStr );
847#endif
848}
849
850
851const wxString& PGM_BASE::GetExecutablePath() const
852{
854}
855
856
862
863
869
870
872{
873 // TODO(JE) much of this code can be shared across the 3 preloads
874 constexpr static int interval = 150;
875 constexpr static int timeLimit = 120000;
876
877 if( m_libraryPreloadInProgress.load() )
878 return;
879
881 Pgm().GetBackgroundJobMonitor().Create( _( "Loading Design Block Libraries" ) );
882
883 auto preload =
884 [this, aKiway]() -> void
885 {
886 std::shared_ptr<BACKGROUND_JOB_REPORTER> reporter =
888
889 DESIGN_BLOCK_LIBRARY_ADAPTER* adapter = aKiway->Prj().DesignBlockLibs();
890
891 int elapsed = 0;
892
893 reporter->Report( _( "Loading Design Block Libraries" ) );
894 adapter->AsyncLoad();
895
896 while( true )
897 {
898 if( m_libraryPreloadAbort.load() )
899 {
900 m_libraryPreloadAbort.store( false );
901 break;
902 }
903
904 std::this_thread::sleep_for( std::chrono::milliseconds( interval ) );
905
906 if( std::optional<float> loadStatus = adapter->AsyncLoadProgress() )
907 {
908 float progress = *loadStatus;
909 reporter->SetCurrentProgress( progress );
910
911 if( progress >= 1 )
912 break;
913 }
914 else
915 {
916 reporter->SetCurrentProgress( 1 );
917 break;
918 }
919
920 elapsed += interval;
921
922 if( elapsed > timeLimit )
923 break;
924 }
925
926 adapter->BlockUntilLoaded();
927
930 m_libraryPreloadInProgress.store( false );
931
932 std::string payload = "";
933 aKiway->ExpressMail( FRAME_SCH, MAIL_RELOAD_LIB, payload );
934 aKiway->ExpressMail( FRAME_PCB_EDITOR, MAIL_RELOAD_LIB, payload );
935 };
936
938 m_libraryPreloadInProgress.store( true );
939 m_libraryPreloadReturn = tp.submit_task( preload );
940}
941
942
944
945
947{
948 wxASSERT( process ); // KIFACE_GETTER has already been called.
949 return *process;
950}
951
952
953// Similar to PGM_BASE& Pgm(), but return nullptr when a *.ki_face is run from a python script.
955{
956 return process;
957}
958
959
960void SetPgm( PGM_BASE* pgm )
961{
962 process = pgm;
963}
const char * name
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
Definition arraydim.h:31
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:104
wxString GetMajorMinorVersion()
Get only the major and minor version in a string major.minor.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void LogAssert(const ASSERT_CACHE_KEY &aKey, const wxString &aMsg)
void LogException(const wxString &aMsg)
void AddTag(const wxString &aKey, const wxString &aValue)
static SENTRY * Instance()
std::shared_ptr< BACKGROUND_JOB > Create(const wxString &aName)
Creates a background job with the given name.
void Remove(std::shared_ptr< BACKGROUND_JOB > job)
Removes the given background job from any lists and frees it.
void InitializeEnvironment()
Creates the built-in environment variables and sets their default values.
void AsyncLoad() override
Loads all available libraries for this adapter type in the background.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
virtual bool SaveToFile(const wxString &aDirectory="", bool aForce=false)
Calls Store() and then writes the contents of the JSON document to a file.
static void Cleanup()
Call curl_global_cleanup for the application.
static void Init()
Call curl_global_init for the application.
A minimalistic software bus for communications between various DLLs/DSOs (DSOs) within the same KiCad...
Definition kiway.h:292
virtual void ExpressMail(FRAME_T aDestination, MAIL_T aCommand, std::string &aPayload, wxWindow *aSource=nullptr, bool aFromOtherThread=false)
Send aPayload to aDestination from aSource.
Definition kiway.cpp:507
virtual PROJECT & Prj() const
Return the PROJECT associated with this KIWAY.
Definition kiway.cpp:200
std::optional< float > AsyncLoadProgress() const
Returns async load progress between 0.0 and 1.0, or nullopt if load is not in progress.
void Load()
Load notifications stored from disk.
static wxString GetInstanceCheckerPath()
Gets the path used for wxSingleInstanceChecker lock files.
Definition paths.cpp:456
static void EnsureUserPathsExist()
Ensures/creates user default paths.
Definition paths.cpp:504
static bool EnsurePathExists(const wxString &aPath, bool aPathToFile=false)
Attempts to create a given path if it does not exist.
Definition paths.cpp:477
static wxString GetLocaleDataPath()
Gets the locales translation data path.
Definition paths.cpp:317
static const wxString & GetExecutablePath()
Definition paths.cpp:629
Container for data for KiCad programs.
Definition pgm_base.h:106
virtual COMMON_SETTINGS * GetCommonSettings() const
Definition pgm_base.cpp:537
virtual wxApp & App()
Return a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
Definition pgm_base.cpp:192
std::unique_ptr< NOTIFICATIONS_MANAGER > m_notifications_manager
Definition pgm_base.h:389
void PreloadDesignBlockLibraries(KIWAY *aKiway)
Starts a background job to preload the global and project design block libraries.
Definition pgm_base.cpp:871
int m_argcUtf8
Definition pgm_base.h:426
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
Definition pgm_base.cpp:783
std::unique_ptr< LIBRARY_MANAGER > m_library_manager
Definition pgm_base.h:387
bool m_Printing
wxWidgets on MSW tends to crash if you spool up more than one print job at a time.
Definition pgm_base.h:365
void setLanguageId(int aId)
Trap all changes in here, simplifies debugging.
Definition pgm_base.h:378
std::unique_ptr< SETTINGS_MANAGER > m_settings_manager
Definition pgm_base.h:386
void loadCommonSettings()
Load internal settings from COMMON_SETTINGS.
Definition pgm_base.cpp:501
virtual void SetPdfBrowserName(const wxString &aFileName)
Definition pgm_base.h:183
wxLocale * m_locale
Definition pgm_base.h:403
void Destroy()
Definition pgm_base.cpp:178
wxSplashScreen * m_splash
Definition pgm_base.h:428
virtual BACKGROUND_JOBS_MONITOR & GetBackgroundJobMonitor() const
Definition pgm_base.h:134
bool InitPgm(bool aHeadless=false, bool aSkipPyInit=false, bool aIsUnitTest=false)
Initialize this program.
Definition pgm_base.cpp:308
char ** m_argvUtf8
argv parameters converted to utf8 form because wxWidgets has opinions.
Definition pgm_base.h:424
virtual void ReadPdfBrowserInfos()
Read the PDF browser choice from the common configuration.
Definition pgm_base.cpp:857
bool IsGUI()
Determine if the application is running with a GUI.
Definition pgm_base.cpp:789
bool m_use_system_pdf_browser
Definition pgm_base.h:406
bool m_Quitting
Definition pgm_base.h:369
std::future< void > m_libraryPreloadReturn
Definition pgm_base.h:431
virtual NOTIFICATIONS_MANAGER & GetNotificationsManager() const
Definition pgm_base.h:139
std::shared_ptr< BACKGROUND_JOB > m_libraryPreloadBackgroundJob
Definition pgm_base.h:430
void BuildArgvUtf8()
Builds the UTF8 based argv variable.
Definition pgm_base.cpp:263
virtual const wxString & GetPdfBrowserName() const
Definition pgm_base.h:181
std::atomic_bool m_libraryPreloadAbort
Definition pgm_base.h:433
virtual void SetTextEditor(const wxString &aFileName)
Definition pgm_base.cpp:199
std::unique_ptr< wxSingleInstanceChecker > m_pgm_checker
Check if there is another copy of Kicad running at the same time.
Definition pgm_base.h:394
virtual bool SetLocalEnvVariable(const wxString &aName, const wxString &aValue)
Set the environment variable aName to aValue.
Definition pgm_base.cpp:736
wxString m_kicad_env
The KICAD system environment variable.
Definition pgm_base.h:401
virtual void ForceSystemPdfBrowser(bool aFlg)
Force the use of system PDF browser, even if a preferred PDF browser is set.
Definition pgm_base.h:198
virtual void SetLocalEnvVariables()
Update the local environment with the contents of the current ENV_VAR_MAP stored in the COMMON_SETTIN...
Definition pgm_base.cpp:767
virtual void SetLanguagePath()
Definition pgm_base.cpp:719
bool SetDefaultLanguage(wxString &aErrMsg)
Set the default language without reference to any preferences.
Definition pgm_base.cpp:644
void ShowSplash()
Definition pgm_base.cpp:278
wxString m_text_editor
Definition pgm_base.h:409
std::atomic_bool m_libraryPreloadInProgress
Definition pgm_base.h:432
virtual ~PGM_BASE()
Definition pgm_base.cpp:161
std::unique_ptr< SCRIPTING > m_python_scripting
Definition pgm_base.h:391
virtual void SetLanguageIdentifier(int menu_id)
Set in .m_language_id member the wxWidgets language identifier ID from the KiCad menu id (internal me...
Definition pgm_base.cpp:685
int m_language_id
Definition pgm_base.h:404
std::unique_ptr< BACKGROUND_JOBS_MONITOR > m_background_jobs_monitor
Definition pgm_base.h:388
void HandleException(std::exception_ptr aPtr)
A exception handler to be used at the top level if exceptions bubble up that for.
Definition pgm_base.cpp:798
void HandleAssert(const wxString &aFile, int aLine, const wxString &aFunc, const wxString &aCond, const wxString &aMsg)
A common assert handler to be used between single_top and kicad.
Definition pgm_base.cpp:823
virtual wxString GetLanguageTag()
Definition pgm_base.cpp:701
virtual const wxString & GetTextEditor(bool aCanShowFileChooser=true)
Return the path to the preferred text editor application.
Definition pgm_base.cpp:206
virtual const wxString & GetExecutablePath() const
Definition pgm_base.cpp:851
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition pgm_base.h:128
void HideSplash()
Definition pgm_base.cpp:297
virtual void WritePdfBrowserInfos()
Save the PDF browser choice to the common configuration.
Definition pgm_base.cpp:864
void SaveCommonSettings()
Save the program (process) settings subset which are stored .kicad_common.
Definition pgm_base.cpp:528
bool m_PropertyGridInitialized
Definition pgm_base.h:371
KICAD_SINGLETON m_singleton
Definition pgm_base.h:411
virtual const wxString AskUserForPreferredEditor(const wxString &aDefaultEditor=wxEmptyString)
Show a dialog that instructs the user to select a new preferred editor.
Definition pgm_base.cpp:242
virtual bool SetLanguage(wxString &aErrMsg, bool first_time=false)
Set the dictionary file name for internationalization.
Definition pgm_base.cpp:543
virtual DESIGN_BLOCK_LIBRARY_ADAPTER * DesignBlockLibs()
Return the table of design block libraries.
Definition project.cpp:448
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Load a project or sets up a new project with a specified path.
bool WarnUserIfOperatingSystemUnsupported()
Checks if the operating system is explicitly unsupported and displays a disclaimer message box.
Definition common.cpp:713
The common library.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
Definition confirm.cpp:230
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
Definition confirm.cpp:202
This file is part of the common library.
#define _(s)
@ FRAME_PCB_EDITOR
Definition frame_type.h:42
@ FRAME_SCH
Definition frame_type.h:34
#define WIN_STRING_DIR_SEP
Definition gestfich.h:38
#define UNIX_STRING_DIR_SEP
Definition gestfich.h:37
const wxChar *const traceLocale
Flag to enable locale debug output.
const wxChar *const traceEnvVars
Flag to enable debug output of environment variable operations.
@ ID_LANGUAGE_SWEDISH
Definition id.h:101
@ ID_LANGUAGE_CATALAN
Definition id.h:90
@ ID_LANGUAGE_NORWEGIAN_BOKMAL
Definition id.h:108
@ ID_LANGUAGE_CHINESE_SIMPLIFIED
Definition id.h:91
@ ID_LANGUAGE_GERMAN
Definition id.h:75
@ ID_LANGUAGE_DUTCH
Definition id.h:93
@ ID_LANGUAGE_GREEK
Definition id.h:76
@ ID_LANGUAGE_HUNGARIAN
Definition id.h:86
@ ID_LANGUAGE_LITHUANIAN
Definition id.h:97
@ ID_LANGUAGE_TAMIL
Definition id.h:109
@ ID_LANGUAGE_PORTUGUESE_BRAZILIAN
Definition id.h:80
@ ID_LANGUAGE_DEFAULT
Definition id.h:68
@ ID_LANGUAGE_POLISH
Definition id.h:87
@ ID_LANGUAGE_THAI
Definition id.h:100
@ ID_LANGUAGE_JAPANESE
Definition id.h:94
@ ID_LANGUAGE_VIETNAMESE
Definition id.h:98
@ ID_LANGUAGE_ITALIAN
Definition id.h:83
@ ID_LANGUAGE_KOREAN
Definition id.h:89
@ ID_LANGUAGE_SERBIAN
Definition id.h:99
@ ID_LANGUAGE_RUSSIAN
Definition id.h:78
@ ID_LANGUAGE_CZECH
Definition id.h:88
@ ID_LANGUAGE_LATVIAN
Definition id.h:96
@ ID_LANGUAGE_SLOVENIAN
Definition id.h:84
@ ID_LANGUAGE_SPANISH
Definition id.h:73
@ ID_LANGUAGE_PORTUGUESE
Definition id.h:79
@ ID_LANGUAGE_ENGLISH
Definition id.h:69
@ ID_LANGUAGE_SPANISH_MEXICAN
Definition id.h:74
@ ID_LANGUAGE_SLOVAK
Definition id.h:85
@ ID_LANGUAGE_CHINESE_TRADITIONAL
Definition id.h:92
@ ID_LANGUAGE_FINNISH
Definition id.h:71
@ ID_LANGUAGE_BULGARIAN
Definition id.h:95
@ ID_LANGUAGE_ARABIC
Definition id.h:103
@ ID_LANGUAGE_UKRAINIAN
Definition id.h:102
@ ID_LANGUAGE_TURKISH
Definition id.h:81
@ ID_LANGUAGE_DANISH
Definition id.h:67
@ ID_LANGUAGE_FRENCH
Definition id.h:70
@ ID_LANGUAGE_HEBREW
Definition id.h:72
@ ID_LANGUAGE_ROMANIAN
Definition id.h:107
@ ID_LANGUAGE_INDONESIAN
Definition id.h:82
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
This file contains miscellaneous commonly used macros and functions.
@ MAIL_RELOAD_LIB
Definition mail_type.h:57
void SetPgm(PGM_BASE *pgm)
Definition pgm_base.cpp:960
static PGM_BASE * process
Definition pgm_base.cpp:943
PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:946
PGM_BASE * PgmOrNull()
Return a reference that can be nullptr when running a shared lib from a script, not from a kicad app.
Definition pgm_base.cpp:954
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition pgm_base.cpp:94
#define _(s)
Current list of languages supported by KiCad.
Definition pgm_base.cpp:93
see class PGM_BASE
KICOMMON_API LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
Definition pgm_base.cpp:94
KICOMMON_API PGM_BASE & Pgm()
The global program "get" accessor.
Definition pgm_base.cpp:946
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
Definition project.h:41
APIIMPORT wxPGGlobalVarsClass * wxPGGlobalVars
wxString From_UTF8(const char *cstring)
This struct represents a key being used for the std::set that deduplicates asserts during this runnin...
Definition app_monitor.h:90
A small class to handle the list of existing translations.
Definition pgm_base.h:72
System directories search utilities.
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
static thread_pool * tp
BS::thread_pool< 0 > thread_pool
Definition thread_pool.h:31
wxLogTrace helper definitions.