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 );
220 m_params.emplace_back(
new PARAM<bool>(
"input.focus_follow_sch_pcb",
221 &m_Input.focus_follow_sch_pcb,
false ) );
223 m_params.emplace_back(
new PARAM<bool>(
"input.auto_pan", &m_Input.auto_pan,
false ) );
225 m_params.emplace_back(
new PARAM<int>(
"input.auto_pan_acceleration",
226 &m_Input.auto_pan_acceleration, 5 ) );
228 m_params.emplace_back(
new PARAM<bool>(
"input.center_on_zoom",
229 &m_Input.center_on_zoom,
true ) );
231 m_params.emplace_back(
new PARAM<bool>(
"input.immediate_actions",
232 &m_Input.immediate_actions,
true ) );
234 m_params.emplace_back(
new PARAM<bool>(
"input.warp_mouse_on_move",
235 &m_Input.warp_mouse_on_move,
true ) );
237 m_params.emplace_back(
new PARAM<bool>(
"input.horizontal_pan",
238 &m_Input.horizontal_pan,
false ) );
240 m_params.emplace_back(
new PARAM<bool>(
"input.hotkey_feedback",
241 &m_Input.hotkey_feedback,
true ) );
243 m_params.emplace_back(
new PARAM<bool>(
"input.zoom_acceleration",
244 &m_Input.zoom_acceleration,
false ) );
247 int default_zoom_speed = 5;
249 int default_zoom_speed = 1;
252 m_params.emplace_back(
new PARAM<int>(
"input.zoom_speed",
253 &m_Input.zoom_speed, default_zoom_speed ) );
255 m_params.emplace_back(
new PARAM<bool>(
"input.zoom_speed_auto",
256 &m_Input.zoom_speed_auto,
true ) );
258 m_params.emplace_back(
new PARAM<int>(
"input.scroll_modifier_zoom",
259 &m_Input.scroll_modifier_zoom, 0 ) );
261 m_params.emplace_back(
new PARAM<int>(
"input.scroll_modifier_pan_h",
262 &m_Input.scroll_modifier_pan_h, WXK_CONTROL ) );
264 m_params.emplace_back(
new PARAM<int>(
"input.scroll_modifier_pan_v",
265 &m_Input.scroll_modifier_pan_v, WXK_SHIFT ) );
267 m_params.emplace_back(
new PARAM<bool>(
"input.reverse_scroll_pan_h",
268 &m_Input.reverse_scroll_pan_h,
false ) );
282 m_params.emplace_back(
new PARAM<int>(
"graphics.opengl_antialiasing_mode",
283 &m_Graphics.opengl_aa_mode, 1, 0, 2 ) );
285 m_params.emplace_back(
new PARAM<int>(
"graphics.cairo_antialiasing_mode",
286 &m_Graphics.cairo_aa_mode, 0, 0, 2 ) );
288 m_params.emplace_back(
new PARAM<int>(
"system.autosave_interval",
289 &m_System.autosave_interval, 600 ) );
293 &m_System.text_editor, wxS(
"/usr/bin/open -e" ) ) );
296 &m_System.text_editor, wxS(
"" ) ) );
299#if defined( __WINDOWS__ )
301 &m_System.file_explorer, wxS(
"explorer.exe /n,/select,%F" ) ) );
304 &m_System.file_explorer, wxS(
"" ) ) );
307 m_params.emplace_back(
new PARAM<int>(
"system.file_history_size",
308 &m_System.file_history_size, 9 ) );
311 &m_System.language, wxS(
"Default" ) ) );
314 &m_System.pdf_viewer_name, wxS(
"" ) ) );
316 m_params.emplace_back(
new PARAM<bool>(
"system.use_system_pdf_viewer",
317 &m_System.use_system_pdf_viewer,
true ) );
320 &m_System.working_dir, wxS(
"" ) ) );
322 m_params.emplace_back(
new PARAM<int>(
"system.clear_3d_cache_interval",
323 &m_System.clear_3d_cache_interval, 30 ) );
325 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.zone_fill_warning",
326 &m_DoNotShowAgain.zone_fill_warning,
false ) );
328 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.env_var_overwrite_warning",
329 &m_DoNotShowAgain.env_var_overwrite_warning,
false ) );
331 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.scaled_3d_models_warning",
332 &m_DoNotShowAgain.scaled_3d_models_warning,
false ) );
334 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.data_collection_prompt",
335 &m_DoNotShowAgain.data_collection_prompt,
false ) );
337 m_params.emplace_back(
new PARAM<bool>(
"do_not_show_again.update_check_prompt",
338 &m_DoNotShowAgain.update_check_prompt,
false ) );
340 m_params.emplace_back(
new PARAM<bool>(
"session.remember_open_files",
341 &m_Session.remember_open_files,
false ) );
344 &m_Session.pinned_symbol_libs, {} ) );
347 &m_Session.pinned_fp_libs, {} ) );
349 m_params.emplace_back(
new PARAM<int>(
"netclass_panel.sash_pos",
350 &m_NetclassPanel.sash_pos, 160 ) );
352 m_params.emplace_back(
new PARAM<wxString>(
"netclass_panel.eeschema_shown_columns",
353 &m_NetclassPanel.eeschema_visible_columns,
"0 10 11 12 13" ) );
355 m_params.emplace_back(
new PARAM<wxString>(
"netclass_panel.pcbnew_shown_columns",
356 &m_NetclassPanel.pcbnew_visible_columns,
"0 1 2 3 4 5 6 7 8 9" ) );
358 m_params.emplace_back(
new PARAM<int>(
"package_manager.sash_pos",
359 &m_PackageManager.sash_pos, 380 ) );
362 [&]() -> nlohmann::json
364 nlohmann::json ret = {};
366 for(
const GIT_REPOSITORY& repo : m_Git.repositories )
368 nlohmann::json repoJson = {};
370 repoJson[
"name"] = repo.name;
371 repoJson[
"path"] = repo.path;
372 repoJson[
"authType"] = repo.authType;
373 repoJson[
"username"] = repo.username;
374 repoJson[
"ssh_path"] = repo.ssh_path;
375 repoJson[
"active"] = repo.active;
377 ret.push_back( repoJson );
382 [&](
const nlohmann::json& aJson )
384 if( !aJson.is_array() )
387 m_Git.repositories.clear();
389 for(
const auto& repoJson : aJson )
393 repo.name = repoJson[
"name"].get<wxString>();
394 repo.path = repoJson[
"path"].get<wxString>();
395 repo.authType = repoJson[
"authType"].get<wxString>();
396 repo.username = repoJson[
"username"].get<wxString>();
397 repo.ssh_path = repoJson[
"ssh_path"].get<wxString>();
398 repo.active = repoJson[
"active"].get<
bool>();
399 repo.checkValid =
true;
401 m_Git.repositories.push_back( repo );
407 &m_Git.authorName, wxS(
"" ) ) );
410 &m_Git.authorEmail, wxS(
"" ) ) );
412 m_params.emplace_back(
new PARAM<bool>(
"git.useDefaultAuthor",
413 &m_Git.useDefaultAuthor,
true ) );
416 &m_Api.python_interpreter, wxS(
"" ) ) );
418 m_params.emplace_back(
new PARAM<bool>(
"api.enable_server",
419 &m_Api.enable_server,
false ) );
435 nlohmann::json::json_pointer mwp_pointer(
"/input/mousewheel_pan"_json_pointer );
442 m_internals->At(
"input" ).erase(
"mousewheel_pan" );
446 wxLogTrace(
traceSettings, wxT(
"COMMON_SETTINGS::Migrate 0->1: mousewheel_pan not found" ) );
451 ( *m_internals )[nlohmann::json::json_pointer(
"/input/horizontal_pan" )] =
true;
453 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_h" )] = WXK_SHIFT;
454 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_v" )] = 0;
455 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_zoom" )] = WXK_CONTROL;
459 ( *m_internals )[nlohmann::json::json_pointer(
"/input/horizontal_pan" )] =
false;
461 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_h" )] = WXK_CONTROL;
462 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_pan_v" )] = WXK_SHIFT;
463 ( *m_internals )[nlohmann::json::json_pointer(
"/input/scroll_modifier_zoom" )] = 0;
472 nlohmann::json::json_pointer v1_pointer(
"/input/prefer_select_to_drag"_json_pointer );
474 bool prefer_selection =
false;
479 m_internals->at( nlohmann::json::json_pointer(
"/input"_json_pointer ) ).erase(
"prefer_select_to_drag" );
483 wxLogTrace(
traceSettings, wxT(
"COMMON_SETTINGS::Migrate 1->2: prefer_select_to_drag not found" ) );
486 if( prefer_selection )
487 ( *m_internals )[nlohmann::json::json_pointer(
"/input/mouse_left" )] = MOUSE_DRAG_ACTION::SELECT;
489 ( *
m_internals )[nlohmann::json::json_pointer(
"/input/mouse_left" )] = MOUSE_DRAG_ACTION::DRAG_ANY;
499 cfgpath.AppendDir( wxT(
"3d" ) );
500 cfgpath.SetFullName( wxS(
"3Dresolver.cfg" ) );
501 cfgpath.MakeAbsolute();
503 std::vector<LEGACY_3D_SEARCH_PATH> legacyPaths;
507 wxRegEx nonValidCharsRegex( wxS(
"[^A-Z0-9_]+" ), wxRE_ADVANCED );
511 wxString key =
path.m_Alias;
512 const wxString& val =
path.m_Pathvar;
520 key.Replace( wxS(
"-" ), wxS(
"_" ) );
523 nonValidCharsRegex.Replace( &key, wxEmptyString );
527 wxLogTrace(
traceEnvVars, wxS(
"COMMON_SETTINGS: Loaded new var: %s = %s" ), key, val );
532 if( cfgpath.FileExists() )
534 wxRemoveFile( cfgpath.GetFullPath() );
545 ret &= fromLegacy<double>( aCfg,
"CanvasScale",
"appearance.canvas_scale" );
546 ret &= fromLegacy<int>( aCfg,
"IconScale",
"appearance.icon_scale" );
547 ret &= fromLegacy<bool>( aCfg,
"UseIconsInMenus",
"appearance.use_icons_in_menus" );
548 ret &= fromLegacy<bool>( aCfg,
"ShowEnvVarWarningDialog",
"environment.show_warning_dialog" );
555 nlohmann::json::json_pointer ptr =
m_internals->PointerFromString(
"environment.vars" );
557 aCfg->SetPath(
"EnvironmentVariables" );
558 ( *m_internals )[ptr] = nlohmann::json( {} );
560 while( aCfg->GetNextEntry( key, index ) )
565 wxT(
"Migrate Env: %s is blacklisted; skipping." ), key );
569 value = aCfg->Read( key, wxEmptyString );
571 if( !value.IsEmpty() )
573 ptr.push_back( key.ToStdString() );
576 ptr.to_string(), value );
577 ( *m_internals )[ptr] = value.ToUTF8();
583 aCfg->SetPath(
".." );
588 bool mousewheel_pan =
false;
590 if( aCfg->Read(
"MousewheelPAN", &mousewheel_pan ) && mousewheel_pan )
592 Set(
"input.horizontal_pan",
true );
593 Set(
"input.scroll_modifier_pan_h",
static_cast<int>( WXK_SHIFT ) );
594 Set(
"input.scroll_modifier_pan_v", 0 );
595 Set(
"input.scroll_modifier_zoom",
static_cast<int>( WXK_CONTROL ) );
598 ret &= fromLegacy<bool>( aCfg,
"AutoPAN",
"input.auto_pan" );
599 ret &= fromLegacy<bool>( aCfg,
"ImmediateActions",
"input.immediate_actions" );
600 ret &= fromLegacy<bool>( aCfg,
"PreferSelectionToDragging",
"input.prefer_select_to_drag" );
601 ret &= fromLegacy<bool>( aCfg,
"MoveWarpsCursor",
"input.warp_mouse_on_move" );
602 ret &= fromLegacy<bool>( aCfg,
"ZoomNoCenter",
"input.center_on_zoom" );
605 if( std::optional<bool> value = Get<bool>(
"input.center_on_zoom" ) )
606 Set(
"input.center_on_zoom", !( *value ) );
608 ret &= fromLegacy<int>( aCfg,
"OpenGLAntialiasingMode",
"graphics.opengl_antialiasing_mode" );
609 ret &= fromLegacy<int>( aCfg,
"CairoAntialiasingMode",
"graphics.cairo_antialiasing_mode" );
611 ret &= fromLegacy<int>( aCfg,
"AutoSaveInterval",
"system.autosave_interval" );
613 ret &= fromLegacy<int>( aCfg,
"FileHistorySize",
"system.file_history_size" );
615 ret &=
fromLegacyString( aCfg,
"PdfBrowserName",
"system.pdf_viewer_name" );
616 ret &= fromLegacy<bool>( aCfg,
"UseSystemBrowser",
"system.use_system_pdf_viewer" );
626 [&](
const wxString& aKey,
const wxString& aDefault )
632 if( wxGetEnv( aKey, &envValue ) ==
true && !envValue.IsEmpty() )
637 wxS(
"InitializeEnvironment: Entry %s defined externally as %s" ), aKey,
642 wxLogTrace(
traceEnvVars, wxS(
"InitializeEnvironment: Setting entry %s to "
650 wxFileName
path( basePath );
651 path.AppendDir( wxT(
"footprints" ) );
655 path.AppendDir( wxT(
"3dmodels" ) );
667 path.AppendDir( wxT(
"symbols" ) );
673 std::vector<LEGACY_3D_SEARCH_PATH>& aSearchPaths )
675 wxFileName cfgpath(
path );
681 wxString cfgname = cfgpath.GetFullPath();
683 std::ifstream cfgFile;
686 if( !wxFileName::Exists( cfgname ) )
688 std::ostringstream ostr;
689 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
690 wxString errmsg =
"no 3D configuration file";
691 ostr <<
" * " << errmsg.ToUTF8() <<
" '";
692 ostr << cfgname.ToUTF8() <<
"'";
697 cfgFile.open( cfgname.ToUTF8() );
699 if( !cfgFile.is_open() )
701 std::ostringstream ostr;
702 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
703 wxString errmsg = wxS(
"Could not open configuration file" );
704 ostr <<
" * " << errmsg.ToUTF8() <<
" '" << cfgname.ToUTF8() <<
"'";
705 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
714 while( cfgFile.good() )
717 std::getline( cfgFile, cfgLine );
720 if( cfgLine.empty() )
728 if( 1 == lineno && cfgLine.compare( 0, 2,
"#V" ) == 0 )
731 if( cfgLine.size() > 2 )
733 std::istringstream istr;
734 istr.str( cfgLine.substr( 2 ) );
748 wxString versionedPath = wxString::Format( wxS(
"${%s}" ),
751 if( al.
m_Alias == versionedPath || al.
m_Alias == wxS(
"${KIPRJMOD}" )
752 || al.
m_Alias == wxS(
"$(KIPRJMOD)" ) || al.
m_Alias == wxS(
"${KISYS3DMOD}" )
753 || al.
m_Alias == wxS(
"$(KISYS3DMOD)" ) )
764 aSearchPaths.push_back( al );
778 if( aIndex >= aString.size() )
780 std::ostringstream ostr;
781 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
782 wxString errmsg = wxS(
"bad Hollerith string on line" );
783 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
784 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
789 size_t i2 = aString.find(
'"', aIndex );
791 if( std::string::npos == i2 )
793 std::ostringstream ostr;
794 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
795 wxString errmsg = wxS(
"missing opening quote mark in config file" );
796 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
797 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
804 if( i2 >= aString.size() )
806 std::ostringstream ostr;
807 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
808 wxString errmsg = wxS(
"invalid entry (unexpected end of line)" );
809 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
810 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
817 while( aString[i2] >=
'0' && aString[i2] <=
'9' )
818 tnum.append( 1, aString[i2++] );
820 if( tnum.empty() || aString[i2++] !=
':' )
822 std::ostringstream ostr;
823 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
824 wxString errmsg = wxS(
"bad Hollerith string on line" );
825 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
826 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
831 std::istringstream istr;
836 if( ( i2 + nchars ) >= aString.size() )
838 std::ostringstream ostr;
839 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
840 wxString errmsg = wxS(
"invalid entry (unexpected end of line)" );
841 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
842 wxLogTrace(
traceSettings, wxS(
"%s\n" ), ostr.str().c_str() );
849 aResult = wxString::FromUTF8( aString.substr( i2, nchars ).c_str() );
853 if( i2 >= aString.size() || aString[i2] !=
'"' )
855 std::ostringstream ostr;
856 ostr << __FILE__ <<
": " << __FUNCTION__ <<
": " << __LINE__ <<
"\n";
857 wxString errmsg = wxS(
"missing closing quote mark in config file" );
858 ostr <<
" * " << errmsg.ToUTF8() <<
"\n'" << aString <<
"'";
859 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().