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" );
454 wxT(
"COMMON_SETTINGS::Migrate 0->1: mousewheel_pan not found" ) );
459 ( *m_internals )[nlohmann::json::json_pointer(
"/input/horizontal_pan" )] =
true;
461 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_h" )] =
463 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_v" )] = 0;
464 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_zoom" )] =
469 ( *m_internals )[nlohmann::json::json_pointer(
"/input/horizontal_pan" )] =
false;
471 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_h" )] =
473 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_v" )] =
475 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_zoom" )] = 0;
484 nlohmann::json::json_pointer v1_pointer(
"/input/prefer_select_to_drag"_json_pointer );
486 bool prefer_selection =
false;
491 m_internals->at( nlohmann::json::json_pointer(
"/input"_json_pointer ) )
492 .erase(
"prefer_select_to_drag" );
497 wxT(
"COMMON_SETTINGS::Migrate 1->2: prefer_select_to_drag not found" ) );
500 if( prefer_selection )
501 ( *m_internals )[nlohmann::json::json_pointer(
"/input/mouse_left" )] =
502 MOUSE_DRAG_ACTION::SELECT;
504 ( *
m_internals )[nlohmann::json::json_pointer(
"/input/mouse_left" )] =
505 MOUSE_DRAG_ACTION::DRAG_ANY;
515 cfgpath.AppendDir( wxT(
"3d" ) );
516 cfgpath.SetFullName( wxS(
"3Dresolver.cfg" ) );
517 cfgpath.MakeAbsolute();
519 std::vector<LEGACY_3D_SEARCH_PATH> legacyPaths;
523 wxRegEx nonValidCharsRegex( wxS(
"[^A-Z0-9_]+" ), wxRE_ADVANCED );
527 wxString key =
path.m_Alias;
528 const wxString& val =
path.m_Pathvar;
537 key.Replace( wxS(
"-" ), wxS(
"_" ) );
540 nonValidCharsRegex.Replace( &key, wxEmptyString );
544 wxLogTrace(
traceEnvVars, wxS(
"COMMON_SETTINGS: Loaded new var: %s = %s" ), key, val );
549 if( cfgpath.FileExists() )
551 wxRemoveFile( cfgpath.GetFullPath() );
562 ret &= fromLegacy<double>( aCfg,
"CanvasScale",
"appearance.canvas_scale" );
563 ret &= fromLegacy<int>( aCfg,
"IconScale",
"appearance.icon_scale" );
564 ret &= fromLegacy<bool>( aCfg,
"UseIconsInMenus",
"appearance.use_icons_in_menus" );
565 ret &= fromLegacy<bool>( aCfg,
"ShowEnvVarWarningDialog",
"environment.show_warning_dialog" );
572 nlohmann::json::json_pointer ptr =
573 m_internals->PointerFromString(
"environment.vars" );
575 aCfg->SetPath(
"EnvironmentVariables" );
576 ( *m_internals )[ptr] = nlohmann::json( {} );
578 while( aCfg->GetNextEntry( key, index ) )
583 wxT(
"Migrate Env: %s is blacklisted; skipping." ), key );
587 value = aCfg->Read( key, wxEmptyString );
589 if( !value.IsEmpty() )
591 ptr.push_back( key.ToStdString() );
594 ptr.to_string(), value );
595 ( *m_internals )[ptr] = value.ToUTF8();
601 aCfg->SetPath(
".." );
606 bool mousewheel_pan =
false;
608 if( aCfg->Read(
"MousewheelPAN", &mousewheel_pan ) && mousewheel_pan )
610 Set(
"input.horizontal_pan",
true );
611 Set(
"input.scroll_modifier_pan_h",
static_cast<int>( WXK_SHIFT ) );
612 Set(
"input.scroll_modifier_pan_v", 0 );
613 Set(
"input.scroll_modifier_zoom",
static_cast<int>( WXK_CONTROL ) );
616 ret &= fromLegacy<bool>( aCfg,
"AutoPAN",
"input.auto_pan" );
617 ret &= fromLegacy<bool>( aCfg,
"ImmediateActions",
"input.immediate_actions" );
618 ret &= fromLegacy<bool>( aCfg,
"PreferSelectionToDragging",
"input.prefer_select_to_drag" );
619 ret &= fromLegacy<bool>( aCfg,
"MoveWarpsCursor",
"input.warp_mouse_on_move" );
620 ret &= fromLegacy<bool>( aCfg,
"ZoomNoCenter",
"input.center_on_zoom" );
623 if( std::optional<bool> value = Get<bool>(
"input.center_on_zoom" ) )
624 Set(
"input.center_on_zoom", !( *value ) );
626 ret &= fromLegacy<int>( aCfg,
"OpenGLAntialiasingMode",
"graphics.opengl_antialiasing_mode" );
627 ret &= fromLegacy<int>( aCfg,
"CairoAntialiasingMode",
"graphics.cairo_antialiasing_mode" );
629 ret &= fromLegacy<int>( aCfg,
"AutoSaveInterval",
"system.autosave_interval" );
631 ret &= fromLegacy<int>( aCfg,
"FileHistorySize",
"system.file_history_size" );
633 ret &=
fromLegacyString( aCfg,
"PdfBrowserName",
"system.pdf_viewer_name" );
634 ret &= fromLegacy<bool>( aCfg,
"UseSystemBrowser",
"system.use_system_pdf_viewer" );
644 [&](
const wxString& aKey,
const wxString& aDefault )
650 if( wxGetEnv( aKey, &envValue ) ==
true && !envValue.IsEmpty() )
655 wxS(
"InitializeEnvironment: Entry %s defined externally as %s" ), aKey,
660 wxLogTrace(
traceEnvVars, wxS(
"InitializeEnvironment: Setting entry %s to "
668 wxFileName
path( basePath );
669 path.AppendDir( wxT(
"footprints" ) );
673 path.AppendDir( wxT(
"3dmodels" ) );
685 path.AppendDir( wxT(
"symbols" ) );
689 path.AppendDir( wxT(
"blocks" ) );
695 std::vector<LEGACY_3D_SEARCH_PATH>& aSearchPaths )
697 wxFileName cfgpath(
path );
703 wxString cfgname = cfgpath.GetFullPath();
705 std::ifstream cfgFile;
708 if( !wxFileName::Exists( cfgname ) )
710 std::ostringstream ostr;
711 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
712 wxString errmsg =
"no 3D configuration file";
713 ostr <<
" * " << errmsg.ToUTF8() <<
" '";
714 ostr << cfgname.ToUTF8() <<
"'";
719 cfgFile.open( cfgname.ToUTF8() );
721 if( !cfgFile.is_open() )
723 std::ostringstream ostr;
724 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
725 wxString errmsg = wxS(
"Could not open configuration file" );
726 ostr <<
" * " << errmsg.ToUTF8() <<
" '" << cfgname.ToUTF8() <<
"'";
727 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
736 while( cfgFile.good() )
739 std::getline( cfgFile, cfgLine );
742 if( cfgLine.empty() )
750 if( 1 == lineno && cfgLine.compare( 0, 2,
"#V" ) == 0 )
753 if( cfgLine.size() > 2 )
755 std::istringstream istr;
756 istr.str( cfgLine.substr( 2 ) );
770 wxString versionedPath = wxString::Format( wxS(
"${%s}" ),
773 if( al.
m_Alias == versionedPath || al.
m_Alias == wxS(
"${KIPRJMOD}" )
774 || al.
m_Alias == wxS(
"$(KIPRJMOD)" ) || al.
m_Alias == wxS(
"${KISYS3DMOD}" )
775 || al.
m_Alias == wxS(
"$(KISYS3DMOD)" ) )
786 aSearchPaths.push_back( al );
800 if( aIndex >= aString.size() )
802 std::ostringstream ostr;
803 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
804 wxString errmsg = wxS(
"bad Hollerith string on line" );
805 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
806 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
811 size_t i2 = aString.find(
'"', aIndex );
813 if( std::string::npos == i2 )
815 std::ostringstream ostr;
816 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
817 wxString errmsg = wxS(
"missing opening quote mark in config file" );
818 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
819 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
826 if( i2 >= aString.size() )
828 std::ostringstream ostr;
829 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
830 wxString errmsg = wxS(
"invalid entry (unexpected end of line)" );
831 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
832 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
839 while( aString[i2] >=
'0' && aString[i2] <=
'9' )
840 tnum.append( 1, aString[i2++] );
842 if( tnum.empty() || aString[i2++] !=
':' )
844 std::ostringstream ostr;
845 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
846 wxString errmsg = wxS(
"bad Hollerith string on line" );
847 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
848 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
853 std::istringstream istr;
858 if( ( i2 + nchars ) >= aString.size() )
860 std::ostringstream ostr;
861 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
862 wxString errmsg = wxS(
"invalid entry (unexpected end of line)" );
863 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
864 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
871 aResult = wxString::FromUTF8( aString.substr( i2, nchars ).c_str() );
875 if( i2 >= aString.size() || aString[i2] !=
'"' )
877 std::ostringstream ostr;
878 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
879 wxString errmsg = wxS(
"missing closing quote mark in config file" );
880 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
881 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)
Construct 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().