33#include <wx/html/htmlwin.h>
36#include <wx/filename.h>
37#include <wx/propgrid/propgrid.h>
38#include <wx/snglinst.h>
39#include <wx/stdpaths.h>
41#include <wx/filedlg.h>
43#include <wx/tooltip.h>
62#include <python_scripting.h>
69#ifdef KICAD_USE_SENTRY
70#include <boost/uuid/uuid_io.hpp>
71#include <boost/uuid/uuid_generators.hpp>
117 wxT(
"简体中文" ),
true },
119 wxT(
"繁體中文" ),
false },
123#define _(s) wxGetTranslation((s))
157#ifdef KICAD_USE_SENTRY
169 wxASSERT( wxTheApp );
187 if( !wxGetEnv( wxT(
"EDITOR" ), &editorname ) )
191 editorname = wxT(
"/usr/bin/open -e" );
193 editorname = wxT(
"/usr/bin/xdg-open" );
199 if( !editorname && aCanShowFileChooser )
208 if( !editorname.IsEmpty() )
221 wxString mask(
_(
"Executable file" ) + wxT(
" (*.exe)|*.exe" ) );
223 wxString mask(
_(
"Executable file" ) + wxT(
" (*)|*" ) );
229 wxFileName::SplitPath( aDefaultEditor, &
path, &
name, &ext );
233 return wxFileSelector(
_(
"Select Preferred Editor" ),
path,
name, wxT(
"." ) + ext,
234 mask, wxFD_OPEN | wxFD_FILE_MUST_EXIST,
nullptr );
238#ifdef KICAD_USE_SENTRY
239bool PGM_BASE::IsSentryOptedIn()
248 return m_sentry_optin_fn.Exists();
252void PGM_BASE::SetSentryOptIn(
bool aOptIn )
256 if( !m_sentry_uid_fn.Exists() )
261 if( !m_sentry_optin_fn.Exists() )
263 wxFFile sentryInitFile( m_sentry_optin_fn.GetFullPath(),
"w" );
264 sentryInitFile.Write(
"" );
265 sentryInitFile.Close();
270 if( m_sentry_optin_fn.Exists() )
272 wxRemoveFile( m_sentry_optin_fn.GetFullPath() );
279wxString PGM_BASE::sentryCreateUid()
281 boost::uuids::uuid uuid = boost::uuids::random_generator()();
282 wxString userGuid = boost::uuids::to_string( uuid );
284 wxFFile sentryInitFile( m_sentry_uid_fn.GetFullPath(),
"w" );
285 sentryInitFile.Write( userGuid );
286 sentryInitFile.Close();
292void PGM_BASE::ResetSentryId()
294 m_sentryUid = sentryCreateUid();
298const wxString& PGM_BASE::GetSentryId()
304void PGM_BASE::sentryInit()
309 if( IsSentryOptedIn() )
311 wxFFile sentryInitFile( m_sentry_uid_fn.GetFullPath() );
312 sentryInitFile.ReadAll( &m_sentryUid );
313 sentryInitFile.Close();
315 if( m_sentryUid.IsEmpty() || m_sentryUid.length() != 36 )
317 m_sentryUid = sentryCreateUid();
320 sentry_options_t* options = sentry_options_new();
322 sentry_options_set_dsn(
328 tmp.AppendDir(
"sentry" );
330 sentry_options_set_database_pathw( options, tmp.GetPathWithSep().wc_str() );
331 sentry_options_set_symbolize_stacktraces( options,
true );
332 sentry_options_set_auto_session_tracking( options,
false );
334 sentry_options_set_release( options,
GetCommitHash().ToStdString().c_str() );
336 sentry_init( options );
338 sentry_value_t user = sentry_value_new_object();
339 sentry_value_set_by_key( user,
"id", sentry_value_new_string( m_sentryUid.c_str() ) );
340 sentry_set_user( user );
342 sentry_set_tag(
"kicad.version",
GetBuildVersion().ToStdString().c_str() );
347void PGM_BASE::sentryPrompt()
356 && !
m_settings_manager->GetCommonSettings()->m_DoNotShowAgain.data_collection_prompt )
358 wxMessageDialog optIn = wxMessageDialog(
360 _(
"KiCad can anonymously report crashes and special event "
361 "data to developers in order to aid identifying critical bugs "
362 "across the user base more effectively and help profile "
363 "functionality to guide improvements. \n"
364 "If you choose to voluntarily participate, KiCad will automatically "
365 "handle sending said reports when crashes or events occur. \n"
366 "Your design files such as schematic or PCB are not shared in this process." ),
367 _(
"Data collection opt in request" ), wxYES_NO | wxCENTRE );
369 int result = optIn.ShowModal();
371 if( result == wxID_YES )
373 SetSentryOptIn(
true );
378 SetSentryOptIn(
false );
381 m_settings_manager->GetCommonSettings()->m_DoNotShowAgain.data_collection_prompt =
true;
389 const wxArrayString& argArray =
App().argv.GetArguments();
395 m_argvUtf8[n] = wxStrdup( argArray[n].ToUTF8() );
404#if defined( __WXMAC__ )
417#ifdef KICAD_USE_SENTRY
423 if(
App().argc == 0 )
424 pgm_name = wxT(
"kicad" );
426 pgm_name = wxFileName(
App().argv[0] ).GetName().Lower();
428#ifdef KICAD_USE_SENTRY
429 sentry_set_tag(
"kicad.app", pgm_name.c_str() );
432 wxInitAllImageHandlers();
436 wxPGInitResourceModule();
439 if( wxString( wxGetenv(
"HOME" ) ).IsEmpty() )
442 "Unable to continue." ) );
450 bool isDefined = wxGetEnv( wxT(
"KICAD" ), &
m_kicad_env );
461 App().SetVendorName( wxT(
"KiCad" ) );
462 App().SetAppName( pgm_name );
465 if( wxImage::FindHandler( wxBITMAP_TYPE_PNG ) ==
nullptr )
466 wxImage::AddHandler(
new wxPNGHandler );
468 if( wxImage::FindHandler( wxBITMAP_TYPE_GIF ) ==
nullptr )
469 wxImage::AddHandler(
new wxGIFHandler );
471 if( wxImage::FindHandler( wxBITMAP_TYPE_JPEG ) ==
nullptr )
472 wxImage::AddHandler(
new wxJPEGHandler );
474 wxFileSystem::AddHandler(
new wxZipFSHandler );
513#ifdef KICAD_USE_SENTRY
532 wxToolTip::Enable(
true );
533 wxToolTip::SetAutoPop( 10000 );
545 m_bin_dir = wxStandardPaths::Get().GetExecutablePath();
553 if( fn.GetName() == wxT(
"kicad" ) || fn.GetName() == wxT(
"kicad-cli" ) )
589 for(
const std::pair<wxString, ENV_VAR_ITEM> it :
GetCommonSettings()->m_Env.vars )
591 wxLogTrace(
traceEnvVars, wxT(
"PGM_BASE::loadSettings: Found entry %s = %s" ),
592 it.first, it.second.GetValue() );
600 if( it.first.IsEmpty() )
604 if( it.second.GetDefinedExternally() )
651 wxString dictionaryName( wxT(
"kicad" ) );
660 wxLogTrace(
traceLocale, wxT(
"This language is not supported by the system." ) );
666 m_locale->Init( wxLANGUAGE_DEFAULT, wxLOCALE_DONT_LOAD_DEFAULT);
668 aErrMsg =
_(
"This language is not supported by the operating system." );
671 else if( !first_time )
673 wxLogTrace(
traceLocale, wxT(
"Search for dictionary %s.mo in %s" ) ,
674 dictionaryName,
m_locale->GetName() );
683 wxString languageSel;
701 if( !
m_locale->IsLoaded( dictionaryName ) )
702 m_locale->AddCatalog( dictionaryName );
710 wxLogTrace(
traceLocale, wxT(
"Unable to load dictionary %s.mo in %s" ),
711 dictionaryName,
m_locale->GetName() );
717 m_locale->Init( wxLANGUAGE_DEFAULT, wxLOCALE_DONT_LOAD_DEFAULT);
719 aErrMsg =
_(
"The KiCad language file for this language is not installed." );
735 wxString dictionaryName( wxT(
"kicad" ) );
742 if( !
m_locale->IsLoaded( dictionaryName ) )
743 m_locale->AddCatalog( dictionaryName );
751 wxLogTrace(
traceLocale, wxT(
"Unable to load dictionary %s.mo in %s" ),
752 dictionaryName,
m_locale->GetName() );
760 aErrMsg =
_(
"The KiCad language file for this language is not installed." );
770 wxLogTrace(
traceLocale, wxT(
"Select language ID %d from %d possible languages." ),
786 const wxLanguageInfo* langInfo = wxLocale::GetLanguageInfo(
m_language_id );
792 #if wxCHECK_VERSION( 3, 1, 6 )
793 wxString str = langInfo->GetCanonicalWithRegion();
795 wxString str = langInfo->CanonicalName;
797 str.Replace(
"_",
"-" );
808 if( wxGetEnv( wxT(
"KICAD_RUN_FROM_BUILD_DIR" ),
nullptr ) )
812 fn.AppendDir( wxT(
"translation" ) );
813 wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
822 if( aName.IsEmpty() )
825 wxT(
"PGM_BASE::SetLocalEnvVariable: Attempt to set empty variable to value %s" ),
831 if( wxGetEnv( aName, &env ) )
834 wxT(
"PGM_BASE::SetLocalEnvVariable: Environment variable %s already set to %s" ),
836 return env == aValue;
840 wxT(
"PGM_BASE::SetLocalEnvVariable: Setting local environment variable %s to %s" ),
843 return wxSetEnv( aName, aValue );
851 for(
const std::pair<wxString, ENV_VAR_ITEM> m_local_env_var :
GetCommonSettings()->m_Env.vars )
854 wxT(
"PGM_BASE::SetLocalEnvVariables: Setting local environment variable %s to %s" ),
855 m_local_env_var.first,
856 m_local_env_var.second.GetValue() );
857 wxSetEnv( m_local_env_var.first, m_local_env_var.second.GetValue() );
873#if wxCHECK_VERSION( 3, 1, 6 )
874 return wxTheApp->IsGUI();
891 std::rethrow_exception( aPtr );
895 wxLogError( ioe.
What() );
897 catch(
const std::exception& e )
899#ifdef KICAD_USE_SENTRY
900 if(
Pgm().IsSentryOptedIn() )
902 sentry_value_t exc = sentry_value_new_exception(
"exception", e.what() );
903 sentry_value_set_stacktrace( exc, NULL, 0 );
905 sentry_value_t sentryEvent = sentry_value_new_event();
906 sentry_event_add_exception( sentryEvent, exc );
907 sentry_capture_event( sentryEvent );
911 wxLogError( wxT(
"Unhandled exception class: %s what: %s" ),
916 wxLogError( wxT(
"Unhandled exception of unknown type" ) );
constexpr std::size_t arrayDim(T const (&)[N]) noexcept
Returns # of elements in an array.
wxString GetCommitHash()
Get the commit hash as a string.
wxString GetBuildVersion()
Get the full KiCad version string.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
void InitializeEnvironment()
Creates the built-in environment variables and sets their default values.
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)
static void Cleanup()
Call curl_global_cleanup for the application.
static void Init()
Call curl_global_init for the application.
static void EnsureUserPathsExist()
Ensures/creates user default paths.
static wxString GetUserCachePath()
Gets the stock (install) 3d viewer plugins path.
static wxString GetLocaleDataPath()
Gets the locales translation data path.
virtual COMMON_SETTINGS * GetCommonSettings() const
virtual wxApp & App()
Returns a bare naked wxApp which may come from wxPython, SINGLE_TOP, or kicad.exe.
int m_argcUtf8
argv parameters converted to utf8 form, because wxwidgets has opinions and will return argv as either...
virtual ENV_VAR_MAP & GetLocalEnvVariables() const
bool setExecutablePath()
Find the path to the executable and stores it in PGM_BASE::m_bin_dir.
bool m_Printing
wxWidgets on MSW tends to crash if you spool up more than one print job at a time.
void setLanguageId(int aId)
Trap all changes in here, simplifies debugging.
std::unique_ptr< SETTINGS_MANAGER > m_settings_manager
void loadCommonSettings()
Loads internal settings from COMMON_SETTINGS.
wxLocale * m_locale
The KICAD system environment variable.
bool InitPgm(bool aHeadless=false, bool aSkipPyInit=false, bool aIsUnitTest=false)
Initialize this program.
virtual void ReadPdfBrowserInfos()
Read the PDF browser choice from the common configuration.
bool IsGUI()
Determine if the application is running with a GUI.
void BuildArgvUtf8()
Builds the UTF8 based argv variable.
virtual void SetTextEditor(const wxString &aFileName)
virtual const wxString & GetExecutablePath() const
virtual bool SetLocalEnvVariable(const wxString &aName, const wxString &aValue)
Sets the environment variable aName to aValue.
wxString m_kicad_env
full path to this program
virtual void ForceSystemPdfBrowser(bool aFlg)
Force the use of system PDF browser, even if a preferred PDF browser is set.
virtual void SetLocalEnvVariables()
Updates the local environment with the contents of the current ENV_VAR_MAP stored in the COMMON_SETTI...
virtual void SetLanguagePath()
bool SetDefaultLanguage(wxString &aErrMsg)
Set the default language without reference to any preferences.
wxString m_text_editor
Filename of the app selected for browsing PDFs.
std::unique_ptr< SCRIPTING > m_python_scripting
virtual void SetLanguageIdentifier(int menu_id)
Set in .m_language_id member the wxWidgets language identifier ID from the KiCad menu id (internal me...
void HandleException(std::exception_ptr aPtr)
A excepion handler to be used at the top level if exceptions bubble up that for.
virtual wxString GetLanguageTag()
virtual const wxString & GetTextEditor(bool aCanShowFileChooser=true)
Return the path to the preferred text editor application.
virtual SETTINGS_MANAGER & GetSettingsManager() const
void SaveCommonSettings()
Save the program (process) settings subset which are stored .kicad_common.
virtual const wxString AskUserForPreferredEditor(const wxString &aDefaultEditor=wxEmptyString)
Shows a dialog that instructs the user to select a new preferred editor.
virtual bool SetLanguage(wxString &aErrMsg, bool first_time=false)
Set the dictionary file name for internationalization.
bool LoadProject(const wxString &aFullPath, bool aSetActive=true)
Loads a project or sets up a new project with a specified path.
#define KICAD_CLI_APP_NAME
bool WarnUserIfOperatingSystemUnsupported()
Checks if the operating system is explicitly unsupported and displays a disclaimer message box.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString &aExtraInfo)
Display an informational message box with aMessage.
void DisplayErrorMessage(wxWindow *aParent, const wxString &aText, const wxString &aExtraInfo)
Display an error message with aMessage.
This file is part of the common library.
Base window classes and related definitions.
#define WIN_STRING_DIR_SEP
#define UNIX_STRING_DIR_SEP
const wxChar *const traceEnvVars
Flag to enable debug output of environment variable operations.
const wxChar *const traceLocale
Flag to enable locale debug output.
@ ID_LANGUAGE_CHINESE_SIMPLIFIED
@ ID_LANGUAGE_PORTUGUESE_BRAZILIAN
@ ID_LANGUAGE_SPANISH_MEXICAN
@ ID_LANGUAGE_CHINESE_TRADITIONAL
std::map< wxString, ENV_VAR_ITEM > ENV_VAR_MAP
This file contains miscellaneous commonly used macros and functions.
static wxString FROM_UTF8(const char *cstring)
Convert a UTF8 encoded C string to a wxString for all wxWidgets build modes.
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
#define _(s)
Current list of languages supported by KiCad.
PGM_BASE & Pgm()
The global Program "get" accessor.
LANGUAGE_DESCR LanguagesList[]
An array containing all the languages that KiCad supports.
#define POLICY_KEY_DATACOLLECTION
#define PROJECT_VAR_NAME
A variable name whose value holds the current project directory.
APIIMPORT wxPGGlobalVarsClass * wxPGGlobalVars
A small class to handle the list of existing translations.
int m_KI_Lang_Identifier
KiCad identifier used in menu selection (See id.h)
wxString m_Lang_Label
Labels used in menus.
System directories search utilities.
wxLogTrace helper definitions.