1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
|
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file pgm_base.cpp
*
* @brief For the main application: init functions, and language selection
* (locale handling)
*/
#include <fctsys.h>
#include <wx/html/htmlwin.h>
#include <wx/fs_zip.h>
#include <wx/dir.h>
#include <wx/filename.h>
#include <wx/snglinst.h>
#include <wx/stdpaths.h>
#include <wx/sysopt.h>
#include <wx/richmsgdlg.h>
#include <pgm_base.h>
#include <draw_frame.h>
#include <eda_base_frame.h>
#include <macros.h>
#include <config_params.h>
#include <id.h>
#include <build_version.h>
#include <hotkeys_basic.h>
#include <gestfich.h>
#include <menus_helpers.h>
#include <confirm.h>
#include <dialog_configure_paths.h>
#include <lockfile.h>
#include <systemdirsappend.h>
#include <trace_helpers.h>
#include <gal/gal_display_options.h>
#define KICAD_COMMON wxT( "kicad_common" )
// some key strings used to store parameters in KICAD_COMMON
const wxChar PGM_BASE::workingDirKey[] = wxT( "WorkingDir" ); // public
static const wxChar languageCfgKey[] = wxT( "LanguageID" );
static const wxChar pathEnvVariables[] = wxT( "EnvironmentVariables" );
static const wxChar showEnvVarWarningDialog[] = wxT( "ShowEnvVarWarningDialog" );
static const wxChar traceEnvVars[] = wxT( "KIENVVARS" );
FILE_HISTORY::FILE_HISTORY( size_t aMaxFiles, int aBaseFileId ) :
wxFileHistory( std::min( aMaxFiles, (size_t) MAX_FILE_HISTORY_SIZE ) )
{
SetBaseId( aBaseFileId );
}
void FILE_HISTORY::SetMaxFiles( size_t aMaxFiles )
{
m_fileMaxFiles = std::min( aMaxFiles, (size_t) MAX_FILE_HISTORY_SIZE );
size_t numFiles = m_fileHistory.size();
while( numFiles > m_fileMaxFiles )
RemoveFileFromHistory( --numFiles );
}
/**
* A small class to handle the list of existing translations.
* The locale translation is automatic.
* The selection of languages is mainly for maintainer's convenience
* To add a support to a new translation:
* create a new icon (flag of the country) (see Lang_Fr.xpm as an example)
* add a new item to s_Languages[].
*/
struct LANGUAGE_DESCR
{
/// wxWidgets locale identifier (See wxWidgets doc)
int m_WX_Lang_Identifier;
/// KiCad identifier used in menu selection (See id.h)
int m_KI_Lang_Identifier;
/// The menu language icons
BITMAP_DEF m_Lang_Icon;
/// Labels used in menus
wxString m_Lang_Label;
/// Set to true if the m_Lang_Label must not be translated
bool m_DoNotTranslate;
};
/**
* Variable s_Languages
* Note: because this list is not created on the fly, wxTranslation
* must be called when a language name must be displayed after translation.
* Do not change this behavior, because m_Lang_Label is also used as key in config
*/
static LANGUAGE_DESCR s_Languages[] =
{
{ wxLANGUAGE_DEFAULT, ID_LANGUAGE_DEFAULT, lang_def_xpm, _( "Default" ) },
{ wxLANGUAGE_ENGLISH, ID_LANGUAGE_ENGLISH, lang_en_xpm, wxT( "English" ), true },
{ wxLANGUAGE_FRENCH, ID_LANGUAGE_FRENCH, lang_fr_xpm, _( "French" ) },
{ wxLANGUAGE_FINNISH, ID_LANGUAGE_FINNISH, lang_fi_xpm, _( "Finnish" ) },
{ wxLANGUAGE_SPANISH, ID_LANGUAGE_SPANISH, lang_es_xpm, _( "Spanish" ) },
{ wxLANGUAGE_PORTUGUESE, ID_LANGUAGE_PORTUGUESE, lang_pt_xpm, _( "Portuguese" ) },
{ wxLANGUAGE_ITALIAN, ID_LANGUAGE_ITALIAN, lang_it_xpm, _( "Italian" ) },
{ wxLANGUAGE_GERMAN, ID_LANGUAGE_GERMAN, lang_de_xpm, _( "German" ) },
{ wxLANGUAGE_GREEK, ID_LANGUAGE_GREEK, lang_gr_xpm, _( "Greek" ) },
{ wxLANGUAGE_SLOVENIAN, ID_LANGUAGE_SLOVENIAN, lang_sl_xpm, _( "Slovenian" ) },
{ wxLANGUAGE_SLOVAK, ID_LANGUAGE_SLOVAK, lang_sk_xpm, _( "Slovak" ) },
{ wxLANGUAGE_HUNGARIAN, ID_LANGUAGE_HUNGARIAN, lang_hu_xpm, _( "Hungarian" ) },
{ wxLANGUAGE_POLISH, ID_LANGUAGE_POLISH, lang_pl_xpm, _( "Polish" ) },
{ wxLANGUAGE_CZECH, ID_LANGUAGE_CZECH, lang_cs_xpm, _( "Czech" ) },
{ wxLANGUAGE_RUSSIAN, ID_LANGUAGE_RUSSIAN, lang_ru_xpm, _( "Russian" ) },
{ wxLANGUAGE_KOREAN, ID_LANGUAGE_KOREAN, lang_ko_xpm, _( "Korean" ) },
{ wxLANGUAGE_CHINESE_SIMPLIFIED, ID_LANGUAGE_CHINESE_SIMPLIFIED, lang_zh_xpm,
_( "Chinese simplified" ) },
{ wxLANGUAGE_CHINESE_TRADITIONAL, ID_LANGUAGE_CHINESE_TRADITIONAL, lang_zh_xpm,
_( "Chinese traditional" ) },
{ wxLANGUAGE_CATALAN, ID_LANGUAGE_CATALAN, lang_ca_xpm, _( "Catalan" ) },
{ wxLANGUAGE_DUTCH, ID_LANGUAGE_DUTCH, lang_nl_xpm, _( "Dutch" ) },
{ wxLANGUAGE_JAPANESE, ID_LANGUAGE_JAPANESE, lang_jp_xpm, _( "Japanese" ) },
{ wxLANGUAGE_BULGARIAN, ID_LANGUAGE_BULGARIAN, lang_bg_xpm, _( "Bulgarian" ) },
{ wxLANGUAGE_LITHUANIAN, ID_LANGUAGE_LITHUANIAN, lang_lt_xpm, _( "Lithuanian" ) }
};
PGM_BASE::PGM_BASE()
{
m_pgm_checker = NULL;
m_locale = NULL;
m_show_env_var_dialog = true;
setLanguageId( wxLANGUAGE_DEFAULT );
ForceSystemPdfBrowser( false );
}
PGM_BASE::~PGM_BASE()
{
Destroy();
}
void PGM_BASE::Destroy()
{
// unlike a normal destructor, this is designed to be called more than once safely:
m_common_settings.reset();
delete m_pgm_checker;
m_pgm_checker = 0;
delete m_locale;
m_locale = 0;
}
wxApp& PGM_BASE::App()
{
wxASSERT( wxTheApp );
return *wxTheApp;
}
void PGM_BASE::SetEditorName( const wxString& aFileName )
{
m_editor_name = aFileName;
wxASSERT( m_common_settings );
m_common_settings->Write( "Editor", aFileName );
}
const wxString& PGM_BASE::GetEditorName( bool aCanShowFileChooser )
{
wxString editorname = m_editor_name;
if( !editorname )
{
if( !wxGetEnv( "EDITOR", &editorname ) )
{
// If there is no EDITOR variable set, try the desktop default
#ifdef __WXMAC__
editorname = "/usr/bin/open";
#elif __WXX11__
editorname = "/usr/bin/xdg-open";
#endif
}
}
// If we still don't have an editor name show a dialog asking the user to select one
if( !editorname && aCanShowFileChooser )
{
DisplayInfoMessage( NULL,
_( "No default editor found, you must choose it" ) );
editorname = AskUserForPreferredEditor();
}
// If we finally have a new editor name request it to be copied to m_editor_name and
// saved to the preferences file.
if( !editorname.IsEmpty() )
SetEditorName( editorname );
// m_editor_name already has the same value that editorname, or empty if no editor was
// found/chosen.
return m_editor_name;
}
const wxString PGM_BASE::AskUserForPreferredEditor( const wxString& aDefaultEditor )
{
// Create a mask representing the executable files in the current platform
#ifdef __WINDOWS__
wxString mask( _( "Executable file (*.exe)|*.exe" ) );
#else
wxString mask( _( "Executable file (*)|*" ) );
#endif
// Extract the path, name and extension from the default editor (even if the editor's
// name was empty, this method will succeed and return empty strings).
wxString path, name, ext;
wxFileName::SplitPath( aDefaultEditor, &path, &name, &ext );
// Show the modal editor and return the file chosen (may be empty if the user cancels
// the dialog).
return EDA_FILE_SELECTOR( _( "Select Preferred Editor" ), path,
name, ext, mask,
NULL, wxFD_OPEN | wxFD_FILE_MUST_EXIST,
true );
}
bool PGM_BASE::InitPgm()
{
wxFileName pgm_name( App().argv[0] );
wxConfigBase::DontCreateOnDemand();
wxInitAllImageHandlers();
m_pgm_checker = new wxSingleInstanceChecker( pgm_name.GetName().Lower() + wxT( "-" ) +
wxGetUserId(), GetKicadLockFilePath() );
if( m_pgm_checker->IsAnotherRunning() )
{
wxString quiz = wxString::Format(
_( "%s is already running. Continue?" ),
GetChars( pgm_name.GetName() )
);
if( !IsOK( NULL, quiz ) )
return false;
}
// Init KiCad environment
// the environment variable KICAD (if exists) gives the kicad path:
// something like set KICAD=d:\kicad
bool isDefined = wxGetEnv( "KICAD", &m_kicad_env );
if( isDefined ) // ensure m_kicad_env ends by "/"
{
m_kicad_env.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
if( !m_kicad_env.IsEmpty() && m_kicad_env.Last() != '/' )
m_kicad_env += UNIX_STRING_DIR_SEP;
}
// Init parameters for configuration
App().SetVendorName( "KiCad" );
App().SetAppName( pgm_name.GetName().Lower() );
// Install some image handlers, mainly for help
if( wxImage::FindHandler( wxBITMAP_TYPE_PNG ) == NULL )
wxImage::AddHandler( new wxPNGHandler );
if( wxImage::FindHandler( wxBITMAP_TYPE_GIF ) == NULL )
wxImage::AddHandler( new wxGIFHandler );
if( wxImage::FindHandler( wxBITMAP_TYPE_JPEG ) == NULL )
wxImage::AddHandler( new wxJPEGHandler );
wxFileSystem::AddHandler( new wxZipFSHandler );
// Analyze the command line & initialize the binary path
setExecutablePath();
SetLanguagePath();
// OS specific instantiation of wxConfigBase derivative:
m_common_settings = GetNewConfig( KICAD_COMMON );
wxString envVarName = wxT( "KIGITHUB" );
ENV_VAR_ITEM envVarItem;
wxString envValue;
wxFileName tmpFileName;
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
envVarItem.SetDefinedExternally( true );
}
else
{
envVarItem.SetValue( wxString( wxT( "https://github.com/KiCad" ) ) );
envVarItem.SetDefinedExternally( false );
}
m_local_env_vars[ envVarName ] = envVarItem;
wxFileName baseSharePath;
#if defined( __WXMSW__ )
// Make the paths relative to the executable dir as KiCad might be installed anywhere
// It follows the Windows installer paths scheme, where binaries are installed in
// PATH/bin and extra files in PATH/share/kicad
baseSharePath.AssignDir( m_bin_dir + "\\.." );
baseSharePath.Normalize();
#else
baseSharePath.AssignDir( wxString( wxT( DEFAULT_INSTALL_PATH ) ) );
#endif
#if !defined( __WXMAC__ )
baseSharePath.AppendDir( "share" );
baseSharePath.AppendDir( "kicad" );
#endif
// KISYSMOD
envVarName = wxT( "KISYSMOD" );
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
envVarItem.SetDefinedExternally( true );
}
else
{
tmpFileName = baseSharePath;
tmpFileName.AppendDir( "modules" );
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetPath() );
m_local_env_vars[ envVarName ] = envVarItem;
// KISYS3DMOD
envVarName = wxT( "KISYS3DMOD" );
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
envVarItem.SetDefinedExternally( true );
}
else
{
tmpFileName.AppendDir( "packages3d" );
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetFullPath() );
m_local_env_vars[ envVarName ] = envVarItem;
// KICAD_TEMPLATE_DIR
envVarName = "KICAD_TEMPLATE_DIR";
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
envVarItem.SetDefinedExternally( true );
}
else
{
// Attempt to find the best default template path.
SEARCH_STACK bases;
SEARCH_STACK templatePaths;
SystemDirsAppend( &bases );
for( unsigned i = 0; i < bases.GetCount(); ++i )
{
wxFileName fn( bases[i], wxEmptyString );
// Add KiCad template file path to search path list.
fn.AppendDir( "template" );
// Only add path if exists and can be read by the user.
if( fn.DirExists() && fn.IsDirReadable() )
{
wxLogTrace( tracePathsAndFiles, "Checking template path '%s' exists",
fn.GetPath() );
templatePaths.AddPaths( fn.GetPath() );
}
}
if( templatePaths.IsEmpty() )
{
tmpFileName = baseSharePath;
tmpFileName.AppendDir( "template" );
}
else
{
// Take the first one. There may be more but this will likely be the best option.
tmpFileName.AssignDir( templatePaths[0] );
}
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetPath() );
m_local_env_vars[ envVarName ] = envVarItem;
// KICAD_USER_TEMPLATE_DIR
envVarName = "KICAD_USER_TEMPLATE_DIR";
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
envVarItem.SetDefinedExternally( true );
}
else
{
// Default user template path.
tmpFileName.AssignDir( wxStandardPaths::Get().GetDocumentsDir() );
tmpFileName.AppendDir( "kicad" );
tmpFileName.AppendDir( "template" );
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetPath() );
m_local_env_vars[ envVarName ] = envVarItem;
// KICAD_SYMBOLS
envVarName = wxT( "KICAD_SYMBOL_DIR" );
if( wxGetEnv( envVarName, &envValue ) == true && !envValue.IsEmpty() )
{
tmpFileName.AssignDir( envValue );
envVarItem.SetDefinedExternally( true );
}
else
{
tmpFileName = baseSharePath;
tmpFileName.AppendDir( "library" );
envVarItem.SetDefinedExternally( false );
}
envVarItem.SetValue( tmpFileName.GetPath() );
m_local_env_vars[ envVarName ] = envVarItem;
ReadPdfBrowserInfos(); // needs m_common_settings
// Init user language *before* calling loadCommonSettings, because
// env vars could be incorrectly initialized on Linux
// (if the value contains some non ASCII7 chars, the env var is not initialized)
SetLanguage( true );
loadCommonSettings();
#ifdef __WXMAC__
// Always show filters on Open dialog to be able to choose plugin
wxSystemOptions::SetOption( wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1 );
#endif
return true;
}
bool PGM_BASE::setExecutablePath()
{
m_bin_dir = wxStandardPaths::Get().GetExecutablePath();
#ifdef __WXMAC__
// On OSX Pgm().GetExecutablePath() will always point to main
// bundle directory, e.g., /Applications/kicad.app/
wxFileName fn( m_bin_dir );
if( fn.GetName() == wxT( "kicad" ) )
{
// kicad launcher, so just remove the Contents/MacOS part
fn.RemoveLastDir();
fn.RemoveLastDir();
}
else
{
// standalone binaries live in Contents/Applications/<standalone>.app/Contents/MacOS
fn.RemoveLastDir();
fn.RemoveLastDir();
fn.RemoveLastDir();
fn.RemoveLastDir();
fn.RemoveLastDir();
}
m_bin_dir = fn.GetPath() + wxT( "/" );
#else
// Use unix notation for paths. I am not sure this is a good idea,
// but it simplifies compatibility between Windows and Unices.
// However it is a potential problem in path handling under Windows.
m_bin_dir.Replace( WIN_STRING_DIR_SEP, UNIX_STRING_DIR_SEP );
// Remove file name form command line:
while( m_bin_dir.Last() != '/' && !m_bin_dir.IsEmpty() )
m_bin_dir.RemoveLast();
#endif
return true;
}
void PGM_BASE::loadCommonSettings()
{
wxASSERT( m_common_settings );
m_help_size.x = 500;
m_help_size.y = 400;
// This only effect the first time KiCad is run. The user's setting will be used for all
// subsequent runs. Menu icons are off by default on OSX and on for all other platforms.
#if defined( __WXMAC__ )
bool defaultUseIconsInMenus = false;
#else
bool defaultUseIconsInMenus = true;
#endif
m_common_settings->Read( showEnvVarWarningDialog, &m_show_env_var_dialog );
if( !m_common_settings->HasEntry( USE_ICONS_IN_MENUS_KEY ) )
m_common_settings->Write( USE_ICONS_IN_MENUS_KEY, defaultUseIconsInMenus );
if( !m_common_settings->HasEntry( ICON_SCALE_KEY )
|| !m_common_settings->HasEntry( GAL_ANTIALIASING_MODE_KEY )
|| !m_common_settings->HasEntry( CAIRO_ANTIALIASING_MODE_KEY ) )
{
// 5.0 and earlier saved common settings in each app, and saved hardware antialiasing
// options only in pcbnew (which was the only canvas to support them). Since there's
// no single right answer to where to pull the common settings from, we might as well
// get them along with the hardware antialiasing option from pcbnew.
auto pcbnewConfig = GetNewConfig( wxString::FromUTF8( "pcbnew" ) );
wxString pcbFrameKey( PCB_EDIT_FRAME_NAME );
if( !m_common_settings->HasEntry( ICON_SCALE_KEY ) )
{
int temp;
wxString msg;
bool option;
pcbnewConfig->Read( "PcbIconScale", &temp, 0 );
m_common_settings->Write( ICON_SCALE_KEY, temp );
pcbnewConfig->Read( ENBL_MOUSEWHEEL_PAN_KEY, &option, false );
m_common_settings->Write( ENBL_MOUSEWHEEL_PAN_KEY, option );
pcbnewConfig->Read( ENBL_ZOOM_NO_CENTER_KEY, &option, false );
m_common_settings->Write( ENBL_ZOOM_NO_CENTER_KEY, option );
pcbnewConfig->Read( ENBL_AUTO_PAN_KEY, &option, true );
m_common_settings->Write( ENBL_AUTO_PAN_KEY, option );
}
if( !m_common_settings->HasEntry( GAL_ANTIALIASING_MODE_KEY ) )
{
int temp;
pcbnewConfig->Read( pcbFrameKey + GAL_DISPLAY_OPTIONS_KEY + GAL_ANTIALIASING_MODE_KEY,
&temp, (int) KIGFX::OPENGL_ANTIALIASING_MODE::NONE );
m_common_settings->Write( GAL_ANTIALIASING_MODE_KEY, temp );
}
if( !m_common_settings->HasEntry( CAIRO_ANTIALIASING_MODE_KEY ) )
{
int temp;
pcbnewConfig->Read( pcbFrameKey + GAL_DISPLAY_OPTIONS_KEY + CAIRO_ANTIALIASING_MODE_KEY,
&temp, (int) KIGFX::CAIRO_ANTIALIASING_MODE::NONE );
m_common_settings->Write( CAIRO_ANTIALIASING_MODE_KEY, temp );
}
}
m_editor_name = m_common_settings->Read( "Editor" );
wxString entry, oldPath;
wxArrayString entries;
long index = 0L;
oldPath = m_common_settings->GetPath();
m_common_settings->SetPath( pathEnvVariables );
while( m_common_settings->GetNextEntry( entry, index ) )
{
wxLogTrace( traceEnvVars,
"Enumerating over entry %s, %ld.", GetChars( entry ), index );
// Do not store the env var PROJECT_VAR_NAME ("KIPRJMOD") definition if for some reason
// it is found in config. (It is reserved and defined as project path)
if( entry == PROJECT_VAR_NAME )
continue;
entries.Add( entry );
}
for( unsigned i = 0; i < entries.GetCount(); i++ )
{
wxString val = m_common_settings->Read( entries[i], wxEmptyString );
if( m_local_env_vars[ entries[i] ].GetDefinedExternally() )
continue;
m_local_env_vars[ entries[i] ] = ENV_VAR_ITEM( val, wxGetEnv( entries[i], NULL ) );
}
for( ENV_VAR_MAP_ITER it = m_local_env_vars.begin(); it != m_local_env_vars.end(); ++it )
{
SetLocalEnvVariable( it->first, it->second.GetValue() );
}
m_common_settings->SetPath( oldPath );
}
void PGM_BASE::SaveCommonSettings()
{
// m_common_settings is not initialized until fairly late in the
// process startup: InitPgm(), so test before using:
if( m_common_settings )
{
wxString cur_dir = wxGetCwd();
m_common_settings->Write( workingDirKey, cur_dir );
m_common_settings->Write( showEnvVarWarningDialog, m_show_env_var_dialog );
// Save the local environment variables.
m_common_settings->SetPath( pathEnvVariables );
for( ENV_VAR_MAP_ITER it = m_local_env_vars.begin(); it != m_local_env_vars.end(); ++it )
{
if( it->second.GetDefinedExternally() )
continue;
wxLogTrace( traceEnvVars, "Saving environment variable config entry %s as %s",
GetChars( it->first ), GetChars( it->second.GetValue() ) );
m_common_settings->Write( it->first, it->second.GetValue() );
}
m_common_settings->SetPath( ".." );
}
}
bool PGM_BASE::SetLanguage( bool first_time )
{
bool retv = true;
if( first_time )
{
setLanguageId( wxLANGUAGE_DEFAULT );
// First time SetLanguage is called, the user selected language id is set
// from commun user config settings
wxString languageSel;
m_common_settings->Read( languageCfgKey, &languageSel );
// Search for the current selection
for( unsigned ii = 0; ii < arrayDim( s_Languages ); ii++ )
{
if( s_Languages[ii].m_Lang_Label == languageSel )
{
setLanguageId( s_Languages[ii].m_WX_Lang_Identifier );
break;
}
}
}
// dictionary file name without extend (full name is kicad.mo)
wxString dictionaryName( "kicad" );
delete m_locale;
m_locale = new wxLocale;
if( !m_locale->Init( m_language_id ) )
{
wxLogTrace( traceLocale, "This language is not supported by the system." );
setLanguageId( wxLANGUAGE_DEFAULT );
delete m_locale;
m_locale = new wxLocale;
m_locale->Init();
retv = false;
}
else if( !first_time )
{
wxLogTrace( traceLocale, "Search for dictionary %s.mo in %s",
GetChars( dictionaryName ), GetChars( m_locale->GetName() ) );
}
if( !first_time )
{
// If we are here, the user has selected another language.
// Therefore the new prefered language name is stored in common config.
// Do NOT store the wxWidgets language Id, it can change between wxWidgets
// versions, for a given language
wxString languageSel;
// Search for the current selection language name
for( unsigned ii = 0; ii < arrayDim( s_Languages ); ii++ )
{
if( s_Languages[ii].m_WX_Lang_Identifier == m_language_id )
{
languageSel = s_Languages[ii].m_Lang_Label;
break;
}
}
m_common_settings->Write( languageCfgKey, languageSel );
}
// Test if floating point notation is working (bug encountered in cross compilation)
// Make a conversion double <=> string
double dtst = 0.5;
wxString msg;
msg << dtst;
double result;
msg.ToDouble( &result );
if( result != dtst )
// string to double encode/decode does not work! Bug detected:
// Disable floating point localization:
setlocale( LC_NUMERIC, "C" );
if( !m_locale->IsLoaded( dictionaryName ) )
m_locale->AddCatalog( dictionaryName );
if( !retv )
return retv;
return m_locale->IsOk();
}
void PGM_BASE::SetLanguageIdentifier( int menu_id )
{
wxLogTrace( traceLocale, "Select language ID %d from %d possible languages.",
menu_id, (int)arrayDim( s_Languages ) );
for( unsigned ii = 0; ii < arrayDim( s_Languages ); ii++ )
{
if( menu_id == s_Languages[ii].m_KI_Lang_Identifier )
{
setLanguageId( s_Languages[ii].m_WX_Lang_Identifier );
break;
}
}
}
void PGM_BASE::SetLanguagePath()
{
SEARCH_STACK guesses;
SystemDirsAppend( &guesses );
// Add our internat dir to the wxLocale catalog of paths
for( unsigned i = 0; i < guesses.GetCount(); i++ )
{
wxFileName fn( guesses[i], wxEmptyString );
// Append path for Windows and unix KiCad package install
fn.AppendDir( "share" );
fn.AppendDir( "internat" );
if( fn.IsDirReadable() )
{
wxLogTrace( traceLocale, "Adding locale lookup path: " + fn.GetPath() );
wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
}
// Append path for unix standard install
fn.RemoveLastDir();
fn.AppendDir( "kicad" );
fn.AppendDir( "internat" );
if( fn.IsDirReadable() )
{
wxLogTrace( traceLocale, "Adding locale lookup path: " + fn.GetPath() );
wxLocale::AddCatalogLookupPathPrefix( fn.GetPath() );
}
}
}
void PGM_BASE::AddMenuLanguageList( wxMenu* MasterMenu )
{
wxMenu* menu = NULL;
wxMenuItem* item = MasterMenu->FindItem( ID_LANGUAGE_CHOICE );
if( item ) // This menu exists, do nothing
return;
menu = new wxMenu;
for( unsigned ii = 0; ii < arrayDim( s_Languages ); ii++ )
{
wxString label;
if( s_Languages[ii].m_DoNotTranslate )
label = s_Languages[ii].m_Lang_Label;
else
label = wxGetTranslation( s_Languages[ii].m_Lang_Label );
AddMenuItem( menu, s_Languages[ii].m_KI_Lang_Identifier,
label, KiBitmap(s_Languages[ii].m_Lang_Icon ),
wxITEM_CHECK );
}
AddMenuItem( MasterMenu, menu,
ID_LANGUAGE_CHOICE,
_( "Set Language" ),
_( "Select application language (only for testing)" ),
KiBitmap( language_xpm ) );
// Set Check mark on current selected language
for( unsigned ii = 0; ii < arrayDim( s_Languages ); ii++ )
{
if( m_language_id == s_Languages[ii].m_WX_Lang_Identifier )
menu->Check( s_Languages[ii].m_KI_Lang_Identifier, true );
else
menu->Check( s_Languages[ii].m_KI_Lang_Identifier, false );
}
}
bool PGM_BASE::SetLocalEnvVariable( const wxString& aName, const wxString& aValue )
{
wxString env;
// Check to see if the environment variable is already set.
if( wxGetEnv( aName, &env ) )
{
wxLogTrace( traceEnvVars, "Environment variable %s already set to %s.",
GetChars( aName ), GetChars( env ) );
return env == aValue;
}
wxLogTrace( traceEnvVars, "Setting local environment variable %s to %s.",
GetChars( aName ), GetChars( aValue ) );
return wxSetEnv( aName, aValue );
}
void PGM_BASE::SetLocalEnvVariables( const ENV_VAR_MAP& aEnvVarMap )
{
m_local_env_vars.clear();
m_local_env_vars = aEnvVarMap;
if( m_common_settings )
m_common_settings->DeleteGroup( pathEnvVariables );
SaveCommonSettings();
// Overwrites externally defined environment variable until the next time the application
// is run.
for( ENV_VAR_MAP_ITER it = m_local_env_vars.begin(); it != m_local_env_vars.end(); ++it )
{
wxLogTrace( traceEnvVars, "Setting local environment variable %s to %s.",
GetChars( it->first ), GetChars( it->second.GetValue() ) );
wxSetEnv( it->first, it->second.GetValue() );
}
}
|