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, 2, 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 ) );
422 m_params.emplace_back(
new PARAM<bool>(
"git.enableGit",
423 &m_Git.enableGit,
true ) );
425 m_params.emplace_back(
new PARAM<int>(
"git.updatInterval",
426 &m_Git.updatInterval, 5 ) );
429 &m_Api.python_interpreter, wxS(
"" ) ) );
431 m_params.emplace_back(
new PARAM<bool>(
"api.enable_server",
432 &m_Api.enable_server,
false ) );
448 nlohmann::json::json_pointer mwp_pointer(
"/input/mousewheel_pan"_json_pointer );
455 m_internals->At(
"input" ).erase(
"mousewheel_pan" );
460 wxT(
"COMMON_SETTINGS::Migrate 0->1: mousewheel_pan not found" ) );
465 ( *m_internals )[nlohmann::json::json_pointer(
"/input/horizontal_pan" )] =
true;
467 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_h" )] =
469 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_v" )] = 0;
470 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_zoom" )] =
475 ( *m_internals )[nlohmann::json::json_pointer(
"/input/horizontal_pan" )] =
false;
477 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_h" )] =
479 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_v" )] =
481 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_zoom" )] = 0;
490 nlohmann::json::json_pointer v1_pointer(
"/input/prefer_select_to_drag"_json_pointer );
492 bool prefer_selection =
false;
497 m_internals->at( nlohmann::json::json_pointer(
"/input"_json_pointer ) )
498 .erase(
"prefer_select_to_drag" );
503 wxT(
"COMMON_SETTINGS::Migrate 1->2: prefer_select_to_drag not found" ) );
506 if( prefer_selection )
507 ( *m_internals )[nlohmann::json::json_pointer(
"/input/mouse_left" )] =
508 MOUSE_DRAG_ACTION::SELECT;
510 ( *
m_internals )[nlohmann::json::json_pointer(
"/input/mouse_left" )] =
511 MOUSE_DRAG_ACTION::DRAG_ANY;
521 cfgpath.AppendDir( wxT(
"3d" ) );
522 cfgpath.SetFullName( wxS(
"3Dresolver.cfg" ) );
523 cfgpath.MakeAbsolute();
525 std::vector<LEGACY_3D_SEARCH_PATH> legacyPaths;
529 wxRegEx nonValidCharsRegex( wxS(
"[^A-Z0-9_]+" ), wxRE_ADVANCED );
533 wxString key =
path.m_Alias;
534 const wxString& val =
path.m_Pathvar;
543 key.Replace( wxS(
"-" ), wxS(
"_" ) );
546 nonValidCharsRegex.Replace( &key, wxEmptyString );
550 wxLogTrace(
traceEnvVars, wxS(
"COMMON_SETTINGS: Loaded new var: %s = %s" ), key, val );
555 if( cfgpath.FileExists() )
557 wxRemoveFile( cfgpath.GetFullPath() );
568 ret &= fromLegacy<double>( aCfg,
"CanvasScale",
"appearance.canvas_scale" );
569 ret &= fromLegacy<int>( aCfg,
"IconScale",
"appearance.icon_scale" );
570 ret &= fromLegacy<bool>( aCfg,
"UseIconsInMenus",
"appearance.use_icons_in_menus" );
571 ret &= fromLegacy<bool>( aCfg,
"ShowEnvVarWarningDialog",
"environment.show_warning_dialog" );
578 nlohmann::json::json_pointer ptr =
579 m_internals->PointerFromString(
"environment.vars" );
581 aCfg->SetPath(
"EnvironmentVariables" );
582 ( *m_internals )[ptr] = nlohmann::json( {} );
584 while( aCfg->GetNextEntry( key, index ) )
589 wxT(
"Migrate Env: %s is blacklisted; skipping." ), key );
593 value = aCfg->Read( key, wxEmptyString );
595 if( !value.IsEmpty() )
597 ptr.push_back( key.ToStdString() );
600 ptr.to_string(), value );
601 ( *m_internals )[ptr] = value.ToUTF8();
607 aCfg->SetPath(
".." );
612 bool mousewheel_pan =
false;
614 if( aCfg->Read(
"MousewheelPAN", &mousewheel_pan ) && mousewheel_pan )
616 Set(
"input.horizontal_pan",
true );
617 Set(
"input.scroll_modifier_pan_h",
static_cast<int>( WXK_SHIFT ) );
618 Set(
"input.scroll_modifier_pan_v", 0 );
619 Set(
"input.scroll_modifier_zoom",
static_cast<int>( WXK_CONTROL ) );
622 ret &= fromLegacy<bool>( aCfg,
"AutoPAN",
"input.auto_pan" );
623 ret &= fromLegacy<bool>( aCfg,
"ImmediateActions",
"input.immediate_actions" );
624 ret &= fromLegacy<bool>( aCfg,
"PreferSelectionToDragging",
"input.prefer_select_to_drag" );
625 ret &= fromLegacy<bool>( aCfg,
"MoveWarpsCursor",
"input.warp_mouse_on_move" );
626 ret &= fromLegacy<bool>( aCfg,
"ZoomNoCenter",
"input.center_on_zoom" );
629 if( std::optional<bool> value = Get<bool>(
"input.center_on_zoom" ) )
630 Set(
"input.center_on_zoom", !( *value ) );
632 ret &= fromLegacy<int>( aCfg,
"OpenGLAntialiasingMode",
"graphics.opengl_antialiasing_mode" );
633 ret &= fromLegacy<int>( aCfg,
"CairoAntialiasingMode",
"graphics.cairo_antialiasing_mode" );
635 ret &= fromLegacy<int>( aCfg,
"AutoSaveInterval",
"system.autosave_interval" );
637 ret &= fromLegacy<int>( aCfg,
"FileHistorySize",
"system.file_history_size" );
639 ret &=
fromLegacyString( aCfg,
"PdfBrowserName",
"system.pdf_viewer_name" );
640 ret &= fromLegacy<bool>( aCfg,
"UseSystemBrowser",
"system.use_system_pdf_viewer" );
650 [&](
const wxString& aKey,
const wxString& aDefault )
656 if( wxGetEnv( aKey, &envValue ) ==
true && !envValue.IsEmpty() )
661 wxS(
"InitializeEnvironment: Entry %s defined externally as %s" ), aKey,
666 wxLogTrace(
traceEnvVars, wxS(
"InitializeEnvironment: Setting entry %s to "
674 wxFileName
path( basePath );
675 path.AppendDir( wxT(
"footprints" ) );
679 path.AppendDir( wxT(
"3dmodels" ) );
691 path.AppendDir( wxT(
"symbols" ) );
695 path.AppendDir( wxT(
"blocks" ) );
701 std::vector<LEGACY_3D_SEARCH_PATH>& aSearchPaths )
703 wxFileName cfgpath(
path );
709 wxString cfgname = cfgpath.GetFullPath();
711 std::ifstream cfgFile;
714 if( !wxFileName::Exists( cfgname ) )
716 std::ostringstream ostr;
717 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
718 wxString errmsg =
"no 3D configuration file";
719 ostr <<
" * " << errmsg.ToUTF8() <<
" '";
720 ostr << cfgname.ToUTF8() <<
"'";
725 cfgFile.open( cfgname.ToUTF8() );
727 if( !cfgFile.is_open() )
729 std::ostringstream ostr;
730 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
731 wxString errmsg = wxS(
"Could not open configuration file" );
732 ostr <<
" * " << errmsg.ToUTF8() <<
" '" << cfgname.ToUTF8() <<
"'";
733 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
742 while( cfgFile.good() )
745 std::getline( cfgFile, cfgLine );
748 if( cfgLine.empty() )
756 if( 1 == lineno && cfgLine.compare( 0, 2,
"#V" ) == 0 )
759 if( cfgLine.size() > 2 )
761 std::istringstream istr;
762 istr.str( cfgLine.substr( 2 ) );
776 wxString versionedPath = wxString::Format( wxS(
"${%s}" ),
779 if( al.
m_Alias == versionedPath || al.
m_Alias == wxS(
"${KIPRJMOD}" )
780 || al.
m_Alias == wxS(
"$(KIPRJMOD)" ) || al.
m_Alias == wxS(
"${KISYS3DMOD}" )
781 || al.
m_Alias == wxS(
"$(KISYS3DMOD)" ) )
792 aSearchPaths.push_back( al );
806 if( aIndex >= aString.size() )
808 std::ostringstream ostr;
809 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
810 wxString errmsg = wxS(
"bad Hollerith string on line" );
811 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
812 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
817 size_t i2 = aString.find(
'"', aIndex );
819 if( std::string::npos == i2 )
821 std::ostringstream ostr;
822 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
823 wxString errmsg = wxS(
"missing opening quote mark in config file" );
824 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
825 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
832 if( i2 >= aString.size() )
834 std::ostringstream ostr;
835 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
836 wxString errmsg = wxS(
"invalid entry (unexpected end of line)" );
837 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
838 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
845 while( aString[i2] >=
'0' && aString[i2] <=
'9' )
846 tnum.append( 1, aString[i2++] );
848 if( tnum.empty() || aString[i2++] !=
':' )
850 std::ostringstream ostr;
851 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
852 wxString errmsg = wxS(
"bad Hollerith string on line" );
853 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
854 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
859 std::istringstream istr;
864 if( ( i2 + nchars ) >= aString.size() )
866 std::ostringstream ostr;
867 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
868 wxString errmsg = wxS(
"invalid entry (unexpected end of line)" );
869 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
870 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
877 aResult = wxString::FromUTF8( aString.substr( i2, nchars ).c_str() );
881 if( i2 >= aString.size() || aString[i2] !=
'"' )
883 std::ostringstream ostr;
884 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
885 wxString errmsg = wxS(
"missing closing quote mark in config file" );
886 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
887 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().