62#if defined( __WXGTK__ ) || defined( __WXMSW__ )
124 [&]() -> nlohmann::json
126 nlohmann::json ret = {};
128 for(
const std::pair<wxString, ENV_VAR_ITEM> entry :
m_Env.
vars )
130 const ENV_VAR_ITEM& var = entry.second;
132 wxASSERT( entry.first == var.GetKey() );
135 if( var.IsDefault() )
137 wxLogTrace( traceEnvVars,
138 wxS(
"COMMON_SETTINGS: Env var %s skipping save (default)" ),
143 wxString value = var.GetValue();
147 if( var.GetDefinedExternally() )
149 if( var.GetDefinedInSettings() )
151 wxLogTrace( traceEnvVars,
152 wxS(
"COMMON_SETTINGS: Env var %s was overridden "
153 "externally, saving previously-loaded value %s" ),
154 var.GetKey(), var.GetSettingsValue() );
155 value = var.GetSettingsValue();
159 wxLogTrace( traceEnvVars,
160 wxS(
"COMMON_SETTINGS: Env var %s skipping save "
168 wxS(
"COMMON_SETTINGS: Saving env var %s = %s" ),
169 var.GetKey(), value);
171 std::string key( var.GetKey().ToUTF8() );
172 ret[ std::move( key ) ] = value;
177 [&](
const nlohmann::json& aJson )
179 if( !aJson.is_object() )
182 for(
const auto& entry : aJson.items() )
184 wxString key = wxString( entry.key().c_str(), wxConvUTF8 );
185 wxString val = entry.value().get<wxString>();
187 if( m_Env.vars.count( key ) )
189 if( m_Env.vars[key].GetDefinedExternally() )
192 wxS(
"COMMON_SETTINGS: %s is defined externally" ),
194 m_Env.vars[key].SetDefinedInSettings();
195 m_Env.vars[key].SetSettingsValue( val );
201 wxS(
"COMMON_SETTINGS: Updating %s: %s -> %s"),
202 key, m_Env.vars[key].GetValue(), val );
203 m_Env.vars[key].SetValue( val );
209 wxS(
"COMMON_SETTINGS: Loaded new var: %s = %s" ),
214 m_Env.vars[key].SetDefinedInSettings();
215 m_Env.vars[key].SetSettingsValue( val );
219 envVarsParam->SetClearUnknownKeys();
221 m_params.emplace_back(
new PARAM<bool>(
"input.focus_follow_sch_pcb",
222 &m_Input.focus_follow_sch_pcb,
false ) );
224 m_params.emplace_back(
new PARAM<bool>(
"input.auto_pan", &m_Input.auto_pan,
false ) );
226 m_params.emplace_back(
new PARAM<int>(
"input.auto_pan_acceleration",
227 &m_Input.auto_pan_acceleration, 5 ) );
229 m_params.emplace_back(
new PARAM<bool>(
"input.center_on_zoom",
230 &m_Input.center_on_zoom,
true ) );
232 m_params.emplace_back(
new PARAM<bool>(
"input.immediate_actions",
233 &m_Input.immediate_actions,
true ) );
235 m_params.emplace_back(
new PARAM<bool>(
"input.warp_mouse_on_move",
236 &m_Input.warp_mouse_on_move,
true ) );
238 m_params.emplace_back(
new PARAM<bool>(
"input.horizontal_pan",
239 &m_Input.horizontal_pan,
false ) );
241 m_params.emplace_back(
new PARAM<bool>(
"input.hotkey_feedback",
242 &m_Input.hotkey_feedback,
true ) );
244 m_params.emplace_back(
new PARAM<bool>(
"input.zoom_acceleration",
245 &m_Input.zoom_acceleration,
false ) );
248 int default_zoom_speed = 5;
250 int default_zoom_speed = 1;
253 m_params.emplace_back(
new PARAM<int>(
"input.zoom_speed",
254 &m_Input.zoom_speed, default_zoom_speed ) );
256 m_params.emplace_back(
new PARAM<bool>(
"input.zoom_speed_auto",
257 &m_Input.zoom_speed_auto,
true ) );
259 m_params.emplace_back(
new PARAM<int>(
"input.scroll_modifier_zoom",
260 &m_Input.scroll_modifier_zoom, 0 ) );
262 m_params.emplace_back(
new PARAM<int>(
"input.scroll_modifier_pan_h",
263 &m_Input.scroll_modifier_pan_h, WXK_CONTROL ) );
265 m_params.emplace_back(
new PARAM<int>(
"input.scroll_modifier_pan_v",
266 &m_Input.scroll_modifier_pan_v, WXK_SHIFT ) );
268 m_params.emplace_back(
new PARAM<bool>(
"input.reverse_scroll_zoom",
269 &m_Input.reverse_scroll_zoom,
false ) );
271 m_params.emplace_back(
new PARAM<bool>(
"input.reverse_scroll_pan_h",
272 &m_Input.reverse_scroll_pan_h,
false ) );
286 m_params.emplace_back(
new PARAM<int>(
"graphics.opengl_antialiasing_mode",
287 &m_Graphics.opengl_aa_mode, 1, 0, 2 ) );
289 m_params.emplace_back(
new PARAM<int>(
"graphics.cairo_antialiasing_mode",
290 &m_Graphics.cairo_aa_mode, 0, 0, 2 ) );
292 m_params.emplace_back(
new PARAM<int>(
"system.autosave_interval",
293 &m_System.autosave_interval, 600 ) );
297 &m_System.text_editor, wxS(
"/usr/bin/open -e" ) ) );
300 &m_System.text_editor, wxS(
"" ) ) );
303#if defined( __WINDOWS__ )
305 &m_System.file_explorer, wxS(
"explorer.exe /n,/select,%F" ) ) );
308 &m_System.file_explorer, wxS(
"" ) ) );
311 m_params.emplace_back(
new PARAM<int>(
"system.file_history_size",
312 &m_System.file_history_size, 9 ) );
315 &m_System.language, wxS(
"Default" ) ) );
318 &m_System.pdf_viewer_name, wxS(
"" ) ) );
320 m_params.emplace_back(
new PARAM<bool>(
"system.use_system_pdf_viewer",
321 &m_System.use_system_pdf_viewer,
true ) );
324 &m_System.working_dir, wxS(
"" ) ) );
326 m_params.emplace_back(
new PARAM<int>(
"system.clear_3d_cache_interval",
327 &m_System.clear_3d_cache_interval, 30 ) );
329 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.zone_fill_warning",
330 &m_DoNotShowAgain.zone_fill_warning,
false ) );
332 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.env_var_overwrite_warning",
333 &m_DoNotShowAgain.env_var_overwrite_warning,
false ) );
335 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.scaled_3d_models_warning",
336 &m_DoNotShowAgain.scaled_3d_models_warning,
false ) );
338 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.data_collection_prompt",
339 &m_DoNotShowAgain.data_collection_prompt,
false ) );
341 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.update_check_prompt",
342 &m_DoNotShowAgain.update_check_prompt,
false ) );
344 m_params.emplace_back(
new PARAM<bool>(
"session.remember_open_files",
345 &m_Session.remember_open_files,
false ) );
348 &m_Session.pinned_symbol_libs, {} ) );
351 &m_Session.pinned_fp_libs, {} ) );
354 &m_Session.pinned_design_block_libs, {} ) );
356 m_params.emplace_back(
new PARAM<int>(
"netclass_panel.sash_pos",
357 &m_NetclassPanel.sash_pos, 160 ) );
359 m_params.emplace_back(
new PARAM<wxString>(
"netclass_panel.eeschema_shown_columns",
360 &m_NetclassPanel.eeschema_visible_columns,
"0 10 11 12 13" ) );
362 m_params.emplace_back(
new PARAM<wxString>(
"netclass_panel.pcbnew_shown_columns",
363 &m_NetclassPanel.pcbnew_visible_columns,
"0 1 2 3 4 5 6 7 8 9" ) );
365 m_params.emplace_back(
new PARAM<int>(
"package_manager.sash_pos",
366 &m_PackageManager.sash_pos, 380 ) );
369 [&]() -> nlohmann::json
371 nlohmann::json ret = {};
373 for(
const GIT_REPOSITORY& repo : m_Git.repositories )
375 nlohmann::json repoJson = {};
377 repoJson[
"name"] = repo.name;
378 repoJson[
"path"] = repo.path;
379 repoJson[
"authType"] = repo.authType;
380 repoJson[
"username"] = repo.username;
381 repoJson[
"ssh_path"] = repo.ssh_path;
382 repoJson[
"active"] = repo.active;
384 ret.push_back( repoJson );
389 [&](
const nlohmann::json& aJson )
391 if( !aJson.is_array() )
394 m_Git.repositories.clear();
396 for(
const auto& repoJson : aJson )
400 repo.name = repoJson[
"name"].get<wxString>();
401 repo.path = repoJson[
"path"].get<wxString>();
402 repo.authType = repoJson[
"authType"].get<wxString>();
403 repo.username = repoJson[
"username"].get<wxString>();
404 repo.ssh_path = repoJson[
"ssh_path"].get<wxString>();
405 repo.active = repoJson[
"active"].get<
bool>();
406 repo.checkValid =
true;
408 m_Git.repositories.push_back( repo );
414 &m_Git.authorName, wxS(
"" ) ) );
417 &m_Git.authorEmail, wxS(
"" ) ) );
419 m_params.emplace_back(
new PARAM<bool>(
"git.useDefaultAuthor",
420 &m_Git.useDefaultAuthor,
true ) );
423 &m_Api.python_interpreter, wxS(
"" ) ) );
425 m_params.emplace_back(
new PARAM<bool>(
"api.enable_server",
426 &m_Api.enable_server,
false ) );
442 nlohmann::json::json_pointer mwp_pointer(
"/input/mousewheel_pan"_json_pointer );
449 m_internals->At(
"input" ).erase(
"mousewheel_pan" );
453 wxLogTrace(
traceSettings, wxT(
"COMMON_SETTINGS::Migrate 0->1: mousewheel_pan not found" ) );
458 ( *m_internals )[nlohmann::json::json_pointer(
"/input/horizontal_pan" )] =
true;
460 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_h" )] = WXK_SHIFT;
461 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_v" )] = 0;
462 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_zoom" )] = WXK_CONTROL;
466 ( *m_internals )[nlohmann::json::json_pointer(
"/input/horizontal_pan" )] =
false;
468 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_h" )] = WXK_CONTROL;
469 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_v" )] = WXK_SHIFT;
470 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_zoom" )] = 0;
479 nlohmann::json::json_pointer v1_pointer(
"/input/prefer_select_to_drag"_json_pointer );
481 bool prefer_selection =
false;
486 m_internals->at( nlohmann::json::json_pointer(
"/input"_json_pointer ) ).erase(
"prefer_select_to_drag" );
490 wxLogTrace(
traceSettings, wxT(
"COMMON_SETTINGS::Migrate 1->2: prefer_select_to_drag not found" ) );
493 if( prefer_selection )
494 ( *m_internals )[nlohmann::json::json_pointer(
"/input/mouse_left" )] = MOUSE_DRAG_ACTION::SELECT;
496 ( *
m_internals )[nlohmann::json::json_pointer(
"/input/mouse_left" )] = MOUSE_DRAG_ACTION::DRAG_ANY;
506 cfgpath.AppendDir( wxT(
"3d" ) );
507 cfgpath.SetFullName( wxS(
"3Dresolver.cfg" ) );
508 cfgpath.MakeAbsolute();
510 std::vector<LEGACY_3D_SEARCH_PATH> legacyPaths;
514 wxRegEx nonValidCharsRegex( wxS(
"[^A-Z0-9_]+" ), wxRE_ADVANCED );
518 wxString key =
path.m_Alias;
519 const wxString& val =
path.m_Pathvar;
527 key.Replace( wxS(
"-" ), wxS(
"_" ) );
530 nonValidCharsRegex.Replace( &key, wxEmptyString );
534 wxLogTrace(
traceEnvVars, wxS(
"COMMON_SETTINGS: Loaded new var: %s = %s" ), key, val );
539 if( cfgpath.FileExists() )
541 wxRemoveFile( cfgpath.GetFullPath() );
552 ret &= fromLegacy<double>( aCfg,
"CanvasScale",
"appearance.canvas_scale" );
553 ret &= fromLegacy<int>( aCfg,
"IconScale",
"appearance.icon_scale" );
554 ret &= fromLegacy<bool>( aCfg,
"UseIconsInMenus",
"appearance.use_icons_in_menus" );
555 ret &= fromLegacy<bool>( aCfg,
"ShowEnvVarWarningDialog",
"environment.show_warning_dialog" );
562 nlohmann::json::json_pointer ptr =
m_internals->PointerFromString(
"environment.vars" );
564 aCfg->SetPath(
"EnvironmentVariables" );
565 ( *m_internals )[ptr] = nlohmann::json( {} );
567 while( aCfg->GetNextEntry( key, index ) )
572 wxT(
"Migrate Env: %s is blacklisted; skipping." ), key );
576 value = aCfg->Read( key, wxEmptyString );
578 if( !value.IsEmpty() )
580 ptr.push_back( key.ToStdString() );
583 ptr.to_string(), value );
584 ( *m_internals )[ptr] = value.ToUTF8();
590 aCfg->SetPath(
".." );
595 bool mousewheel_pan =
false;
597 if( aCfg->Read(
"MousewheelPAN", &mousewheel_pan ) && mousewheel_pan )
599 Set(
"input.horizontal_pan",
true );
600 Set(
"input.scroll_modifier_pan_h",
static_cast<int>( WXK_SHIFT ) );
601 Set(
"input.scroll_modifier_pan_v", 0 );
602 Set(
"input.scroll_modifier_zoom",
static_cast<int>( WXK_CONTROL ) );
605 ret &= fromLegacy<bool>( aCfg,
"AutoPAN",
"input.auto_pan" );
606 ret &= fromLegacy<bool>( aCfg,
"ImmediateActions",
"input.immediate_actions" );
607 ret &= fromLegacy<bool>( aCfg,
"PreferSelectionToDragging",
"input.prefer_select_to_drag" );
608 ret &= fromLegacy<bool>( aCfg,
"MoveWarpsCursor",
"input.warp_mouse_on_move" );
609 ret &= fromLegacy<bool>( aCfg,
"ZoomNoCenter",
"input.center_on_zoom" );
612 if( std::optional<bool> value = Get<bool>(
"input.center_on_zoom" ) )
613 Set(
"input.center_on_zoom", !( *value ) );
615 ret &= fromLegacy<int>( aCfg,
"OpenGLAntialiasingMode",
"graphics.opengl_antialiasing_mode" );
616 ret &= fromLegacy<int>( aCfg,
"CairoAntialiasingMode",
"graphics.cairo_antialiasing_mode" );
618 ret &= fromLegacy<int>( aCfg,
"AutoSaveInterval",
"system.autosave_interval" );
620 ret &= fromLegacy<int>( aCfg,
"FileHistorySize",
"system.file_history_size" );
622 ret &=
fromLegacyString( aCfg,
"PdfBrowserName",
"system.pdf_viewer_name" );
623 ret &= fromLegacy<bool>( aCfg,
"UseSystemBrowser",
"system.use_system_pdf_viewer" );
633 [&](
const wxString& aKey,
const wxString& aDefault )
639 if( wxGetEnv( aKey, &envValue ) ==
true && !envValue.IsEmpty() )
644 wxS(
"InitializeEnvironment: Entry %s defined externally as %s" ), aKey,
649 wxLogTrace(
traceEnvVars, wxS(
"InitializeEnvironment: Setting entry %s to "
657 wxFileName
path( basePath );
658 path.AppendDir( wxT(
"footprints" ) );
662 path.AppendDir( wxT(
"3dmodels" ) );
674 path.AppendDir( wxT(
"symbols" ) );
678 path.AppendDir( wxT(
"blocks" ) );
684 std::vector<LEGACY_3D_SEARCH_PATH>& aSearchPaths )
686 wxFileName cfgpath(
path );
692 wxString cfgname = cfgpath.GetFullPath();
694 std::ifstream cfgFile;
697 if( !wxFileName::Exists( cfgname ) )
699 std::ostringstream ostr;
700 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
701 wxString errmsg =
"no 3D configuration file";
702 ostr <<
" * " << errmsg.ToUTF8() <<
" '";
703 ostr << cfgname.ToUTF8() <<
"'";
708 cfgFile.open( cfgname.ToUTF8() );
710 if( !cfgFile.is_open() )
712 std::ostringstream ostr;
713 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
714 wxString errmsg = wxS(
"Could not open configuration file" );
715 ostr <<
" * " << errmsg.ToUTF8() <<
" '" << cfgname.ToUTF8() <<
"'";
716 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
725 while( cfgFile.good() )
728 std::getline( cfgFile, cfgLine );
731 if( cfgLine.empty() )
739 if( 1 == lineno && cfgLine.compare( 0, 2,
"#V" ) == 0 )
742 if( cfgLine.size() > 2 )
744 std::istringstream istr;
745 istr.str( cfgLine.substr( 2 ) );
759 wxString versionedPath = wxString::Format( wxS(
"${%s}" ),
762 if( al.
m_Alias == versionedPath || al.
m_Alias == wxS(
"${KIPRJMOD}" )
763 || al.
m_Alias == wxS(
"$(KIPRJMOD)" ) || al.
m_Alias == wxS(
"${KISYS3DMOD}" )
764 || al.
m_Alias == wxS(
"$(KISYS3DMOD)" ) )
775 aSearchPaths.push_back( al );
789 if( aIndex >= aString.size() )
791 std::ostringstream ostr;
792 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
793 wxString errmsg = wxS(
"bad Hollerith string on line" );
794 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
795 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
800 size_t i2 = aString.find(
'"', aIndex );
802 if( std::string::npos == i2 )
804 std::ostringstream ostr;
805 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
806 wxString errmsg = wxS(
"missing opening quote mark in config file" );
807 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
808 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
815 if( i2 >= aString.size() )
817 std::ostringstream ostr;
818 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
819 wxString errmsg = wxS(
"invalid entry (unexpected end of line)" );
820 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
821 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
828 while( aString[i2] >=
'0' && aString[i2] <=
'9' )
829 tnum.append( 1, aString[i2++] );
831 if( tnum.empty() || aString[i2++] !=
':' )
833 std::ostringstream ostr;
834 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
835 wxString errmsg = wxS(
"bad Hollerith string on line" );
836 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
837 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
842 std::istringstream istr;
847 if( ( i2 + nchars ) >= aString.size() )
849 std::ostringstream ostr;
850 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
851 wxString errmsg = wxS(
"invalid entry (unexpected end of line)" );
852 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
853 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
860 aResult = wxString::FromUTF8( aString.substr( i2, nchars ).c_str() );
864 if( i2 >= aString.size() || aString[i2] !=
'"' )
866 std::ostringstream ostr;
867 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
868 wxString errmsg = wxS(
"missing closing quote mark in config file" );
869 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
870 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
static bool getLegacy3DHollerith(const std::string &aString, size_t &aIndex, wxString &aResult)
bool readLegacy3DResolverCfg(const wxString &aPath, std::vector< LEGACY_3D_SEARCH_PATH > &aSearchPaths)
void InitializeEnvironment()
Creates the built-in environment variables and sets their default values.
virtual bool MigrateFromLegacy(wxConfigBase *aLegacyConfig) override
Migrates from wxConfig to JSON-based configuration.
KiCad uses environment variables internally for determining the base paths for libraries,...
bool fromLegacyString(wxConfigBase *aConfig, const std::string &aKey, const std::string &aDest)
Translates a legacy wxConfig string value to a given JSON pointer value.
void Set(const std::string &aPath, ValueType aVal)
Stores a value into the JSON document Will throw an exception if ValueType isn't something that the l...
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
std::unique_ptr< JSON_SETTINGS_INTERNALS > m_internals
Stores an enum as an integer.
Like a normal param, but with custom getter and setter functions.
static wxString GetUserTemplatesPath()
Gets the user path for custom templates.
static wxString GetStockEDALibraryPath()
Gets the stock (install) EDA library data path, which is the base path for templates,...
static wxString GetDefault3rdPartyPath()
Gets the default path for PCM packages.
static wxString GetStockTemplatesPath()
Gets the stock (install) templates path.
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
const int commonSchemaVersion
! Update the schema version whenever a migration is required
const wxRegEx versionedEnvVarRegex(wxS("KICAD[0-9]+_[A-Z0-9_]+(_DIR)?"))
! The following environment variables will never be migrated from a previous version
const wxRegEx versionedEnvVarRegex(wxS("KICAD[0-9]+_[A-Z0-9_]+(_DIR)?"))
Functions related to environment variables, including help functions.
const wxChar *const traceEnvVars
Flag to enable debug output of environment variable operations.
@ USER
The main config directory (e.g. ~/.config/kicad/)
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Constructs a versioned environment variable based on this KiCad major version.
bool apply_icon_scale_to_fonts
double hicontrast_dimming_factor
int min_interval
Minimum time, in seconds, between subsequent backups.
bool backup_on_autosave
Trigger a backup on autosave.
unsigned long long limit_total_size
Maximum total size of backups (bytes), 0 for unlimited.
int limit_total_files
Maximum number of backup archives to retain.
int limit_daily_files
Maximum files to keep per day, 0 for unlimited.
bool enabled
Automatically back up the project when files are saved.
System directories search utilities.
wxLogTrace helper definitions.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().