KiCad PCB EDA Suite
Loading...
Searching...
No Matches
common_settings.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2020 Jon Evans <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <set>
22#include <fstream>
23#include <sstream>
24
26#include <env_vars.h>
27#include <paths.h>
28#include <richio.h>
29#include <search_stack.h>
35#include <settings/parameters.h>
36#include <systemdirsappend.h>
37#include <trace_helpers.h>
38#include <wx/config.h>
39#include <wx/log.h>
40#include <wx/regex.h>
41#include <wx/tokenzr.h>
42#include <wx/window.h>
43
44
46const wxRegEx versionedEnvVarRegex( wxS( "KICAD[0-9]+_[A-Z0-9_]+(_DIR)?" ) );
47
49const int commonSchemaVersion = 7;
50
52
56 m_Backup(),
57 m_Env(),
58 m_Input(),
60 m_Graphics(),
61 m_Session(),
62 m_System(),
65 m_Api(),
68{
69 /*
70 * Automatic dark mode detection works fine on Mac.
71 */
72#if defined( __WXGTK__ ) || defined( __WXMSW__ )
73 m_params.emplace_back( new PARAM_ENUM<ICON_THEME>( "appearance.icon_theme",
75#else
76 m_Appearance.icon_theme = ICON_THEME::AUTO;
77#endif
78
79#if defined( __WXMSW__ )
80 m_params.emplace_back( new PARAM_ENUM<APP_THEME>( "appearance.app_theme", &m_Appearance.app_theme,
82#else
83 m_Appearance.app_theme = APP_THEME::AUTO;
84#endif
85
86 /*
87 * Automatic canvas scaling works fine on all supported platforms, so it's no longer exposed as
88 * a configuration option.
89 */
90 m_Appearance.canvas_scale = 0.0;
91
92 /*
93 * Menu icons are off by default on OSX and on for all other platforms.
94 */
95#ifdef __WXMAC__
96 m_params.emplace_back( new PARAM<bool>( "appearance.use_icons_in_menus",
97 &m_Appearance.use_icons_in_menus, false ) );
98#else
99 m_params.emplace_back( new PARAM<bool>( "appearance.use_icons_in_menus",
100 &m_Appearance.use_icons_in_menus, true ) );
101#endif
102
103 /*
104 * Font scaling hacks are only needed on GTK under wxWidgets 3.0.
105 */
106 m_Appearance.apply_icon_scale_to_fonts = false;
107
108 m_params.emplace_back( new PARAM<bool>( "appearance.show_scrollbars",
109 &m_Appearance.show_scrollbars, false ) );
110
111 m_params.emplace_back( new PARAM<double>( "appearance.hicontrast_dimming_factor",
112 &m_Appearance.hicontrast_dimming_factor, 0.8f ) );
113
114 m_params.emplace_back( new PARAM<int>( "appearance.text_editor_zoom",
115 &m_Appearance.text_editor_zoom, 0 ) );
116
117 m_params.emplace_back( new PARAM<int>( "appearance.toolbar_icon_size",
118 &m_Appearance.toolbar_icon_size, 24, 16, 64 ) );
119
120 m_params.emplace_back( new PARAM<bool>( "appearance.grid_striping",
121 &m_Appearance.grid_striping, false ) );
122
123 m_params.emplace_back( new PARAM<bool>( "appearance.use_custom_cursors",
124 &m_Appearance.use_custom_cursors, true ) );
125
126 m_Appearance.zoom_correction_factor = 1.0;
127 m_params.emplace_back( new PARAM<double>( "appearance.zoom_correction_factor",
128 &m_Appearance.zoom_correction_factor, 1.0, 0.1, 10.0 ) );
129
130 m_params.emplace_back( new PARAM<bool>( "auto_backup.enabled", &m_Backup.enabled, true ) );
131
132 m_params.emplace_back( new PARAM_ENUM<BACKUP_FORMAT>( "auto_backup.format", &m_Backup.format,
134
135 m_params.emplace_back( new PARAM_ENUM<BACKUP_LOCATION>( "auto_backup.location",
138
139 m_params.emplace_back( new PARAM<unsigned long long>( "auto_backup.limit_total_size",
140 &m_Backup.limit_total_size, 104857600 ) );
141
142 auto envVarsParam = m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "environment.vars",
143 [&]() -> nlohmann::json
144 {
145 nlohmann::json ret = nlohmann::json::object();
146
147 for( const std::pair<wxString, ENV_VAR_ITEM> entry : m_Env.vars )
148 {
149 const ENV_VAR_ITEM& var = entry.second;
150
151 wxASSERT( entry.first == var.GetKey() );
152
153 // Default values are never persisted
154 if( var.IsDefault() )
155 {
156 wxLogTrace( traceEnvVars,
157 wxS( "COMMON_SETTINGS: Env var %s skipping save (default)" ),
158 var.GetKey() );
159 continue;
160 }
161
162 wxString value = var.GetValue();
163
164 value.Trim( true ).Trim( false ); // Trim from both sides
165
166 // Vars that existed in JSON are persisted, but if they were overridden
167 // externally, we persist the old value (i.e. the one that was loaded from JSON)
168 if( var.GetDefinedExternally() )
169 {
170 if( var.GetDefinedInSettings() )
171 {
172 wxLogTrace( traceEnvVars,
173 wxS( "COMMON_SETTINGS: Env var %s was overridden "
174 "externally, saving previously-loaded value %s" ),
175 var.GetKey(), var.GetSettingsValue() );
176 value = var.GetSettingsValue();
177 }
178 else
179 {
180 wxLogTrace( traceEnvVars,
181 wxS( "COMMON_SETTINGS: Env var %s skipping save "
182 "(external)" ),
183 var.GetKey() );
184 continue;
185 }
186 }
187
188 wxLogTrace( traceEnvVars,
189 wxS( "COMMON_SETTINGS: Saving env var %s = %s" ),
190 var.GetKey(), value);
191
192 std::string key( var.GetKey().Trim( true ).Trim( false ).ToUTF8() );
193 ret[ std::move( key ) ] = value;
194 }
195
196 return ret;
197 },
198 [&]( const nlohmann::json& aJson )
199 {
200 if( !aJson.is_object() )
201 return;
202
203 for( const auto& entry : aJson.items() )
204 {
205 wxString key = wxString( entry.key().c_str(), wxConvUTF8 ).Trim( true ).Trim( false );
206 wxString val = entry.value().get<wxString>().Trim( true ).Trim( false );
207
208 if( m_Env.vars.count( key ) )
209 {
210 if( m_Env.vars[key].GetDefinedExternally() )
211 {
212 wxLogTrace( traceEnvVars,
213 wxS( "COMMON_SETTINGS: %s is defined externally" ),
214 key );
215 m_Env.vars[key].SetDefinedInSettings();
216 m_Env.vars[key].SetSettingsValue( val );
217 continue;
218 }
219 else
220 {
221 wxLogTrace( traceEnvVars,
222 wxS( "COMMON_SETTINGS: Updating %s: %s -> %s"),
223 key, m_Env.vars[key].GetValue(), val );
224 m_Env.vars[key].SetValue( val );
225 }
226 }
227 else
228 {
229 wxLogTrace( traceEnvVars,
230 wxS( "COMMON_SETTINGS: Loaded new var: %s = %s" ),
231 key, val );
232 m_Env.vars[key] = ENV_VAR_ITEM( key, val );
233 }
234
235 m_Env.vars[key].SetDefinedInSettings();
236 m_Env.vars[key].SetSettingsValue( val );
237 }
238 },
239 {} ) );
240 envVarsParam->SetClearUnknownKeys();
241
242 m_params.emplace_back( new PARAM<bool>( "input.focus_follow_sch_pcb",
243 &m_Input.focus_follow_sch_pcb, false ) );
244
245 m_params.emplace_back( new PARAM<bool>( "input.auto_pan", &m_Input.auto_pan, false ) );
246
247 m_params.emplace_back( new PARAM<int>( "input.auto_pan_acceleration",
248 &m_Input.auto_pan_acceleration, 5 ) );
249
250 m_params.emplace_back( new PARAM<bool>( "input.center_on_zoom",
251 &m_Input.center_on_zoom, true ) );
252
253 m_params.emplace_back( new PARAM<bool>( "input.immediate_actions",
254 &m_Input.immediate_actions, true ) );
255
256 m_params.emplace_back( new PARAM<bool>( "input.warp_mouse_on_move",
257 &m_Input.warp_mouse_on_move, true ) );
258
259 m_params.emplace_back( new PARAM<bool>( "input.horizontal_pan",
260 &m_Input.horizontal_pan, true ) );
261
262 m_params.emplace_back( new PARAM<bool>( "input.hotkey_feedback",
263 &m_Input.hotkey_feedback, true ) );
264
265 m_params.emplace_back( new PARAM<bool>( "input.zoom_acceleration",
266 &m_Input.zoom_acceleration, false ) );
267
268#ifdef __WXMAC__
269 int default_zoom_speed = 5;
270#else
271 int default_zoom_speed = 1;
272#endif
273
274 m_params.emplace_back( new PARAM<int>( "input.zoom_speed",
275 &m_Input.zoom_speed, default_zoom_speed ) );
276
277 m_params.emplace_back( new PARAM<bool>( "input.zoom_speed_auto",
278 &m_Input.zoom_speed_auto, true ) );
279
280#ifdef __WXMSW__
281 constexpr TOUCHPAD_MODE defaultTouchpadMode = TOUCHPAD_MODE::NATIVE_GESTURES;
282#else
283 constexpr TOUCHPAD_MODE defaultTouchpadMode = TOUCHPAD_MODE::SCROLL_GESTURES;
284#endif
285
286 m_params.emplace_back( new PARAM_ENUM<TOUCHPAD_MODE>( "input.touchpad_mode",
287 &m_Input.touchpad_mode, defaultTouchpadMode, TOUCHPAD_MODE::NATIVE_GESTURES,
289
290 m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_zoom",
291 &m_Input.scroll_modifier_zoom, 0 ) );
292
293 m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_pan_h",
294 &m_Input.scroll_modifier_pan_h, WXK_CONTROL ) );
295
296 m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_pan_v",
297 &m_Input.scroll_modifier_pan_v, WXK_SHIFT ) );
298
299 m_params.emplace_back( new PARAM<int>( "input.motion_pan_modifier",
300 &m_Input.motion_pan_modifier, 0 ) );
301
302 m_params.emplace_back( new PARAM<bool>( "input.reverse_scroll_zoom",
303 &m_Input.reverse_scroll_zoom, false ) );
304
305 m_params.emplace_back( new PARAM<bool>( "input.reverse_scroll_pan_h",
306 &m_Input.reverse_scroll_pan_h, false ) );
307
308 m_params.emplace_back( new PARAM_ENUM<MOUSE_DRAG_ACTION>( "input.mouse_left",
311
312 m_params.emplace_back( new PARAM_ENUM<MOUSE_DRAG_ACTION>( "input.mouse_middle",
315
316 m_params.emplace_back( new PARAM_ENUM<MOUSE_DRAG_ACTION>( "input.mouse_right",
319
320 m_params.emplace_back( new PARAM<int>( "spacemouse.rotate_speed",
321 &m_SpaceMouse.rotate_speed, 5, 1, 10 ) );
322
323 m_params.emplace_back( new PARAM<int>( "spacemouse.pan_speed",
324 &m_SpaceMouse.pan_speed, 5, 1, 10 ) );
325
326 m_params.emplace_back( new PARAM<bool>( "spacemouse.reverse_rotate",
327 &m_SpaceMouse.reverse_rotate, false ) );
328
329 m_params.emplace_back( new PARAM<bool>( "spacemouse.reverse_pan_x",
330 &m_SpaceMouse.reverse_pan_x, false ) );
331
332 m_params.emplace_back( new PARAM<bool>( "spacemouse.reverse_pan_y",
333 &m_SpaceMouse.reverse_pan_y, false ) );
334
335 m_params.emplace_back( new PARAM<bool>( "spacemouse.reverse_zoom",
336 &m_SpaceMouse.reverse_zoom, false ) );
337
338 m_params.emplace_back( new PARAM<int>( "graphics.canvas_type",
339 &m_Graphics.canvas_type, EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL ) );
340
341 m_params.emplace_back( new PARAM<int>( "graphics.antialiasing_mode",
342 &m_Graphics.aa_mode, 2, 0, 2 ) );
343
344 m_params.emplace_back( new PARAM<int>( "system.local_history_debounce",
345 &m_System.local_history_debounce, 5, 0, 100000 ) );
346
347#ifdef __WXMAC__
348 m_params.emplace_back( new PARAM<wxString>( "system.text_editor",
349 &m_System.text_editor, wxS( "/usr/bin/open -e" ) ) );
350#else
351 m_params.emplace_back( new PARAM<wxString>( "system.text_editor",
352 &m_System.text_editor, wxS( "" ) ) );
353#endif
354
355#if defined( __WINDOWS__ )
356 m_params.emplace_back( new PARAM<wxString>( "system.file_explorer",
357 &m_System.file_explorer, wxS( "explorer.exe /n,/select,%F" ) ) );
358#else
359 m_params.emplace_back( new PARAM<wxString>( "system.file_explorer",
360 &m_System.file_explorer, wxS( "" ) ) );
361#endif
362
363 m_params.emplace_back( new PARAM<int>( "system.file_history_size",
364 &m_System.file_history_size, 9 ) );
365
366 m_params.emplace_back( new PARAM<wxString>( "system.language",
367 &m_System.language, wxS( "Default" ) ) );
368
369 m_params.emplace_back( new PARAM<wxString>( "system.pdf_viewer_name",
370 &m_System.pdf_viewer_name, wxS( "" ) ) );
371
372 m_params.emplace_back( new PARAM<bool>( "system.use_system_pdf_viewer",
373 &m_System.use_system_pdf_viewer, true ) );
374
375 m_params.emplace_back( new PARAM<wxString>( "system.working_dir",
376 &m_System.working_dir, wxS( "" ) ) );
377
378 m_params.emplace_back( new PARAM<int>( "system.clear_3d_cache_interval",
379 &m_System.clear_3d_cache_interval, 30 ) );
380
381 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.zone_fill_warning",
382 &m_DoNotShowAgain.zone_fill_warning, false ) );
383
384 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.env_var_overwrite_warning",
385 &m_DoNotShowAgain.env_var_overwrite_warning, false ) );
386
387 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.scaled_3d_models_warning",
388 &m_DoNotShowAgain.scaled_3d_models_warning, false ) );
389
390 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.data_collection_prompt",
391 &m_DoNotShowAgain.data_collection_prompt, false ) );
392
393 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.update_check_prompt",
394 &m_DoNotShowAgain.update_check_prompt, false ) );
395
396 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.migrate_wrl_prompt",
397 &m_DoNotShowAgain.migrate_wrl_prompt, false ) );
398
399 m_params.emplace_back( new PARAM<bool>( "embed_file_defaults.datasheet", &m_EmbedFileDefaults.datasheet, true ) );
400
401 m_params.emplace_back(
402 new PARAM<bool>( "embed_file_defaults.drawing_sheet", &m_EmbedFileDefaults.drawing_sheet, true ) );
403
404 m_params.emplace_back( new PARAM<bool>( "embed_file_defaults.model_3d", &m_EmbedFileDefaults.model_3d, false ) );
405
406 m_params.emplace_back( new PARAM<bool>( "embed_file_defaults.sim_model", &m_EmbedFileDefaults.sim_model, false ) );
407
408 m_params.emplace_back( new PARAM<bool>( "relative_path_defaults.drawing_sheet",
409 &m_RelativePathDefaults.drawing_sheet, false ) );
410
411 m_params.emplace_back( new PARAM<bool>( "relative_path_defaults.jobset_destination",
412 &m_RelativePathDefaults.jobset_destination, false ) );
413
414 m_params.emplace_back( new PARAM_LIST<wxString>( "system.extra_3d_search_dirs",
415 &m_Extra3DSearchDirs, {} ) );
416
417 m_params.emplace_back( new PARAM_LIST<wxString>( "system.declined_model_preview_requirements",
418 &m_DeclinedModelPreviewRequirements, {} ) );
419
420 m_params.emplace_back( new PARAM<bool>( "session.remember_open_files",
421 &m_Session.remember_open_files, false ) );
422
423 m_params.emplace_back( new PARAM_LIST<wxString>( "session.pinned_symbol_libs",
424 &m_Session.pinned_symbol_libs, {} ) );
425
426 m_params.emplace_back( new PARAM_LIST<wxString>( "session.pinned_fp_libs",
427 &m_Session.pinned_fp_libs, {} ) );
428
429 m_params.emplace_back( new PARAM_LIST<wxString>( "session.pinned_design_block_libs",
430 &m_Session.pinned_design_block_libs, {} ) );
431
432 m_params.emplace_back( new PARAM_LAMBDA<std::string>( "fields.template_field_names",
433 [&]() -> std::string
434 {
435 if( m_FieldNameTemplates.GetTemplateFieldNames( TEMPLATES::SCOPE::GLOBAL ).empty() )
436 return {};
437
438 STRING_FORMATTER formatter;
439 m_FieldNameTemplates.Format( &formatter, TEMPLATES::SCOPE::GLOBAL );
440 return formatter.GetString();
441 },
442 [&]( const std::string& aSerializedTemplates )
443 {
444 m_FieldNameTemplates.DeleteFieldNameTemplates( TEMPLATES::SCOPE::GLOBAL );
445
446 if( !aSerializedTemplates.empty() )
447 {
448 m_FieldNameTemplates.AddTemplateFieldNames(
449 wxString::FromUTF8( aSerializedTemplates ), TEMPLATES::SCOPE::GLOBAL );
450 }
451 }, {} ) );
452
453 m_params.emplace_back( new PARAM<int>( "package_manager.sash_pos",
454 &m_PackageManager.sash_pos, 380 ) );
455
456 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "git.repositories",
457 [&]() -> nlohmann::json
458 {
459 nlohmann::json ret = nlohmann::json::array();
460
461 for( const GIT_REPOSITORY& repo : m_Git.repositories )
462 {
463 nlohmann::json repoJson = {};
464
465 repoJson["name"] = repo.name;
466 repoJson["path"] = repo.path;
467 repoJson["authType"] = repo.authType;
468 repoJson["username"] = repo.username;
469 repoJson["ssh_path"] = repo.ssh_path;
470 repoJson["active"] = repo.active;
471
472 ret.push_back( repoJson );
473 }
474
475 return ret;
476 },
477 [&]( const nlohmann::json& aJson )
478 {
479 if( !aJson.is_array() )
480 return;
481
482 m_Git.repositories.clear();
483
484 for( const auto& repoJson : aJson )
485 {
486 GIT_REPOSITORY repo;
487
488 repo.name = repoJson["name"].get<wxString>();
489 repo.path = repoJson["path"].get<wxString>();
490 repo.authType = repoJson["authType"].get<wxString>();
491 repo.username = repoJson["username"].get<wxString>();
492 repo.ssh_path = repoJson["ssh_path"].get<wxString>();
493 repo.active = repoJson["active"].get<bool>();
494 repo.checkValid = true;
495
496 m_Git.repositories.push_back( repo );
497 }
498 },
499 {} ) );
500
501 m_params.emplace_back( new PARAM<wxString>( "git.authorName",
502 &m_Git.authorName, wxS( "" ) ) );
503
504 m_params.emplace_back( new PARAM<wxString>( "git.authorEmail",
505 &m_Git.authorEmail, wxS( "" ) ) );
506
507 m_params.emplace_back( new PARAM<bool>( "git.useDefaultAuthor",
508 &m_Git.useDefaultAuthor, true ) );
509
510 m_params.emplace_back( new PARAM<bool>( "git.enableGit",
511 &m_Git.enableGit, true ) );
512
513 m_params.emplace_back( new PARAM<int>( "git.updatInterval",
514 &m_Git.updatInterval, 5 ) );
515
516 m_params.emplace_back( new PARAM<bool>( "git.showContributorAvatars", &m_Git.showContributorAvatars, false ) );
517
518 m_params.emplace_back( new PARAM<wxString>( "api.interpreter_path",
519 &m_Api.python_interpreter, wxS( "" ) ) );
520
521 m_params.emplace_back( new PARAM<bool>( "api.enable_server",
522 &m_Api.enable_server, false ) );
523
524 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "dialog.controls",
525 [&]() -> nlohmann::json
526 {
527 nlohmann::json ret = nlohmann::json::object();
528
529 for( const auto& dlg : m_csInternals->m_dialogControlValues )
530 ret[ dlg.first ] = dlg.second;
531
532 return ret;
533 },
534 [&]( const nlohmann::json& aVal )
535 {
536 m_csInternals->m_dialogControlValues.clear();
537
538 if( !aVal.is_object() )
539 return;
540
541 for( auto& [dlgKey, dlgVal] : aVal.items() )
542 {
543 if( !dlgVal.is_object() )
544 continue;
545
546 for( auto& [ctrlKey, ctrlVal] : dlgVal.items() )
547 m_csInternals->m_dialogControlValues[ dlgKey ][ ctrlKey ] = ctrlVal;
548 }
549 },
550 nlohmann::json::object() ) );
551
552 // Let the save drop entries for dialogs and controls that no longer exist
553 m_params.back()->SetClearUnknownKeys();
554
555 registerMigration( 0, 1, std::bind( &COMMON_SETTINGS::migrateSchema0to1, this ) );
556 registerMigration( 1, 2, std::bind( &COMMON_SETTINGS::migrateSchema1to2, this ) );
557 registerMigration( 2, 3, std::bind( &COMMON_SETTINGS::migrateSchema2to3, this ) );
558 registerMigration( 3, 4, std::bind( &COMMON_SETTINGS::migrateSchema3to4, this ) );
559 registerMigration( 4, 5, std::bind( &COMMON_SETTINGS::migrateSchema4to5, this ) );
560 registerMigration( 5, 6, std::bind( &COMMON_SETTINGS::migrateSchema5to6, this ) );
561 registerMigration( 6, 7, std::bind( &COMMON_SETTINGS::migrateSchema6to7, this ) );
562}
563
564
566{
572
573 nlohmann::json::json_pointer mwp_pointer( "/input/mousewheel_pan"_json_pointer );
574
575 bool mwp = false;
576
577 try
578 {
579 mwp = m_internals->at( mwp_pointer );
580 m_internals->At( "input" ).erase( "mousewheel_pan" );
581 }
582 catch( ... )
583 {
584 wxLogTrace( traceSettings,
585 wxT( "COMMON_SETTINGS::Migrate 0->1: mousewheel_pan not found" ) );
586 }
587
588 if( mwp )
589 {
590 ( *m_internals )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = true;
591 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_SHIFT;
592 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = 0;
593 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = WXK_CONTROL;
594 }
595 else
596 {
597 ( *m_internals )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = false;
598 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_CONTROL;
599 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = WXK_SHIFT;
600 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = 0;
601 }
602
603 return true;
604}
605
606
608{
609 nlohmann::json::json_pointer v1_pointer( "/input/prefer_select_to_drag"_json_pointer );
610
611 bool prefer_selection = false;
612
613 try
614 {
615 prefer_selection = m_internals->at( v1_pointer );
616 m_internals->at( nlohmann::json::json_pointer( "/input"_json_pointer ) ).erase( "prefer_select_to_drag" );
617 }
618 catch( ... )
619 {
620 wxLogTrace( traceSettings, wxT( "COMMON_SETTINGS::Migrate 1->2: prefer_select_to_drag not found" ) );
621 }
622
623 if( prefer_selection )
624 ( *m_internals )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::SELECT;
625 else
626 ( *m_internals )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::DRAG_ANY;
627
628 return true;
629}
630
631
633{
634 wxFileName cfgpath;
635 cfgpath.AssignDir( PATHS::GetUserSettingsPath() );
636 cfgpath.AppendDir( wxT( "3d" ) );
637 cfgpath.SetFullName( wxS( "3Dresolver.cfg" ) );
638 cfgpath.MakeAbsolute();
639
640 std::vector<LEGACY_3D_SEARCH_PATH> legacyPaths;
641 readLegacy3DResolverCfg( cfgpath.GetFullPath(), legacyPaths );
642
643 // env variables have a limited allowed character set for names
644 wxRegEx nonValidCharsRegex( wxS( "[^A-Z0-9_]+" ), wxRE_ADVANCED );
645
646 for( const LEGACY_3D_SEARCH_PATH& path : legacyPaths )
647 {
648 wxString key = path.m_Alias;
649 const wxString& val = path.m_Pathvar;
650
651 // The 3d alias config didn't use the same naming restrictions as real env variables
652 // We need to sanitize them
653
654 // upper case only
655 key.MakeUpper();
656
657 // logically swap - with _
658 key.Replace( wxS( "-" ), wxS( "_" ) );
659
660 // remove any other chars
661 nonValidCharsRegex.Replace( &key, wxEmptyString );
662
663 if( !m_Env.vars.count( key ) )
664 {
665 wxLogTrace( traceEnvVars, wxS( "COMMON_SETTINGS: Loaded new var: %s = %s" ), key, val );
666 m_Env.vars[key] = ENV_VAR_ITEM( key, val );
667 }
668 }
669
670 if( cfgpath.FileExists() )
671 {
672 wxRemoveFile( cfgpath.GetFullPath() );
673 }
674
675 return true;
676}
677
678
680{
681 // >= 10 = add 1
682 try
683 {
684 // Update netclass panel shown columns for eeschema
685 const nlohmann::json::json_pointer v3_pointer_eeschema( "/netclass_panel/eeschema_shown_columns"_json_pointer );
686 wxString eeSchemaColumnList_old = m_internals->at( v3_pointer_eeschema );
687
688 wxStringTokenizer eeSchemaShownTokens( eeSchemaColumnList_old, " \t\r\n" );
689 wxString eeSchemaColumnList_new;
690
691 while( eeSchemaShownTokens.HasMoreTokens() )
692 {
693 long colNumber;
694 eeSchemaShownTokens.GetNextToken().ToLong( &colNumber );
695
696 if( colNumber >= 10 )
697 ++colNumber;
698
699 eeSchemaColumnList_new += wxString::Format( wxT( "%ld " ), colNumber );
700 }
701
702 eeSchemaColumnList_new.Trim( true );
703 eeSchemaColumnList_new.Trim( false );
704
705 m_internals->at( v3_pointer_eeschema ) = eeSchemaColumnList_new.ToUTF8();
706
707 // Update netclass panel shown columns for pcbnew
708 const nlohmann::json::json_pointer v3_pointer_pcbnew( "/netclass_panel/pcbnew_shown_columns"_json_pointer );
709 wxString pcbnewColumnList_old = m_internals->at( v3_pointer_pcbnew );
710
711 wxStringTokenizer pcbnewShownTokens( pcbnewColumnList_old, " \t\r\n" );
712 wxString pcbnewColumnList_new;
713
714 while( pcbnewShownTokens.HasMoreTokens() )
715 {
716 long colNumber;
717 pcbnewShownTokens.GetNextToken().ToLong( &colNumber );
718
719 if( colNumber >= 10 )
720 ++colNumber;
721
722 pcbnewColumnList_new += wxString::Format( wxT( "%ld " ), colNumber );
723 }
724
725 pcbnewColumnList_new.Trim( true );
726 pcbnewColumnList_new.Trim( false );
727
728 m_internals->at( v3_pointer_pcbnew ) = pcbnewColumnList_new.ToUTF8();
729 }
730 catch( ... )
731 {
732 wxLogTrace( traceSettings, wxT( "COMMON_SETTINGS::Migrate 3->4: /netclass_panel/shown_columns not found" ) );
733 }
734
735 return true;
736}
737
738
740{
741 try
742 {
743 nlohmann::json& controls = m_internals->At( "dialog" ).at( "controls" );
744
745 for( auto& [dlgKey, dlgVal] : controls.items() )
746 {
747 if( !dlgVal.is_object() )
748 continue;
749
750 auto geoIt = dlgVal.find( "__geometry" );
751
752 if( geoIt == dlgVal.end() || !geoIt->is_object() )
753 continue;
754
755 nlohmann::json& geom = *geoIt;
756
757 // Legacy values were stored in logical pixels. Convert to DIP using the
758 // primary display's scale factor (best approximation without window context).
759 int w = geom.value( "w", 0 );
760 int h = geom.value( "h", 0 );
761
762 wxSize dipSize = wxWindow::ToDIP( wxSize( w, h ), nullptr );
763 geom[ "w" ] = dipSize.x;
764 geom[ "h" ] = dipSize.y;
765
766 geom.erase( "dip" );
767 }
768 }
769 catch( ... )
770 {
771 wxLogTrace( traceSettings, wxT( "COMMON_SETTINGS::Migrate 4->5: dialog.controls not found" ) );
772 }
773
774 return true;
775}
776
777
779{
780 // Schema 6 introduces auto_backup.format and auto_backup.location. Pre-schema-6
781 // installs unconditionally produced timestamped zip archives whenever a save was
782 // eligible for backup, so the new INCREMENTAL default would silently disable archive
783 // creation for users who already had auto_backup.enabled set. Write ZIP into the
784 // upgraded config to preserve their backup behavior; new installs skip the migration
785 // path entirely and keep the new default. The location default (PROJECT_DIR) already
786 // matches the legacy on-disk layout, so we leave it absent.
787 try
788 {
789 if( !Contains( "auto_backup.format" ) )
790 Set<int>( "auto_backup.format", static_cast<int>( BACKUP_FORMAT::ZIP ) );
791 }
792 catch( ... )
793 {
794 wxLogTrace( traceSettings, wxT( "COMMON_SETTINGS::Migrate 5->6: failed to set auto_backup.format" ) );
795 }
796
797 return true;
798}
799
800
802{
803 // Global field name templates used to be stored in eeschema.json. Import them here so
804 // applications which do not load Eeschema can use them immediately after upgrading.
805 if( Contains( "fields.template_field_names" ) )
806 return true;
807
808 wxFileName eeschemaPath( PATHS::GetUserSettingsPath(), wxS( "eeschema.json" ) );
809
810 if( !eeschemaPath.IsFileReadable() )
811 return true;
812
813 try
814 {
815 std::ifstream eeschemaFile( eeschemaPath.GetFullPath().fn_str() );
816 nlohmann::json eeschemaSettings = nlohmann::json::parse( eeschemaFile, nullptr, ALLOW_EXCEPTIONS,
818
819 const nlohmann::json::json_pointer fieldNamesPointer( "/drawing/field_names"_json_pointer );
820
821 if( eeschemaSettings.contains( fieldNamesPointer )
822 && eeschemaSettings.at( fieldNamesPointer ).is_string() )
823 {
824 Set<std::string>( "fields.template_field_names",
825 eeschemaSettings.at( fieldNamesPointer ).get<std::string>() );
826 }
827 }
828 catch( ... )
829 {
830 wxLogTrace( traceSettings, wxT( "COMMON_SETTINGS::Migrate 6->7: failed to import field name templates" ) );
831 }
832
833 return true;
834}
835
836
837bool COMMON_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
838{
839 bool ret = true;
840
841 ret &= fromLegacy<double>( aCfg, "CanvasScale", "appearance.canvas_scale" );
842 ret &= fromLegacy<int>( aCfg, "IconScale", "appearance.icon_scale" );
843 ret &= fromLegacy<bool>( aCfg, "UseIconsInMenus", "appearance.use_icons_in_menus" );
844 ret &= fromLegacy<bool>( aCfg, "ShowEnvVarWarningDialog", "environment.show_warning_dialog" );
845
846 auto load_env_vars =
847 [&]()
848 {
849 wxString key, value;
850 long index = 0;
851 nlohmann::json::json_pointer ptr = m_internals->PointerFromString( "environment.vars" );
852
853 aCfg->SetPath( "EnvironmentVariables" );
854 ( *m_internals )[ptr] = nlohmann::json( {} );
855
856 while( aCfg->GetNextEntry( key, index ) )
857 {
858 if( versionedEnvVarRegex.Matches( key ) )
859 {
860 wxLogTrace( traceSettings,
861 wxT( "Migrate Env: %s is blacklisted; skipping." ), key );
862 continue;
863 }
864
865 value = aCfg->Read( key, wxEmptyString );
866
867 if( !value.IsEmpty() )
868 {
869 ptr.push_back( key.ToStdString() );
870
871 wxLogTrace( traceSettings, wxT( "Migrate Env: %s=%s" ),
872 ptr.to_string(), value );
873 ( *m_internals )[ptr] = value.ToUTF8();
874
875 ptr.pop_back();
876 }
877 }
878
879 aCfg->SetPath( ".." );
880 };
881
882 load_env_vars();
883
884 bool mousewheel_pan = false;
885
886 if( aCfg->Read( "MousewheelPAN", &mousewheel_pan ) && mousewheel_pan )
887 {
888 Set( "input.horizontal_pan", true );
889 Set( "input.scroll_modifier_pan_h", static_cast<int>( WXK_SHIFT ) );
890 Set( "input.scroll_modifier_pan_v", 0 );
891 Set( "input.scroll_modifier_zoom", static_cast<int>( WXK_CONTROL ) );
892 }
893
894 ret &= fromLegacy<bool>( aCfg, "AutoPAN", "input.auto_pan" );
895 ret &= fromLegacy<bool>( aCfg, "ImmediateActions", "input.immediate_actions" );
896 ret &= fromLegacy<bool>( aCfg, "PreferSelectionToDragging", "input.prefer_select_to_drag" );
897 ret &= fromLegacy<bool>( aCfg, "MoveWarpsCursor", "input.warp_mouse_on_move" );
898 ret &= fromLegacy<bool>( aCfg, "ZoomNoCenter", "input.center_on_zoom" );
899
900 // This was stored inverted in legacy config
901 if( std::optional<bool> value = Get<bool>( "input.center_on_zoom" ) )
902 Set( "input.center_on_zoom", !( *value ) );
903
904 ret &= fromLegacy<int>( aCfg, "OpenGLAntialiasingMode", "graphics.antialiasing_mode" );
905
906 // Cairo anti-aliasing modes no longer supported
907 //ret &= fromLegacy<int>( aCfg, "CairoAntialiasingMode", "graphics.cairo_antialiasing_mode" );
908
909 ret &= fromLegacy<int>( aCfg, "AutoSaveInterval", "system.local_history_debounce" );
910 ret &= fromLegacyString( aCfg, "Editor", "system.text_editor" );
911 ret &= fromLegacy<int>( aCfg, "FileHistorySize", "system.file_history_size" );
912 ret &= fromLegacyString( aCfg, "LanguageID", "system.language" );
913 ret &= fromLegacyString( aCfg, "PdfBrowserName", "system.pdf_viewer_name" );
914 ret &= fromLegacy<bool>( aCfg, "UseSystemBrowser", "system.use_system_pdf_viewer" );
915 ret &= fromLegacyString( aCfg, "WorkingDir", "system.working_dir" );
916
917 return ret;
918}
919
920
922{
923 auto addVar =
924 [&]( const wxString& aKey, const wxString& aDefault )
925 {
926 m_Env.vars[aKey] = ENV_VAR_ITEM( aKey, aDefault, aDefault );
927
928 wxString envValue;
929
930 if( wxGetEnv( aKey, &envValue ) == true && !envValue.IsEmpty() )
931 {
932 m_Env.vars[aKey].SetValue( envValue );
933 m_Env.vars[aKey].SetDefinedExternally();
934 wxLogTrace( traceEnvVars, wxS( "InitializeEnvironment: Entry %s defined externally as %s" ),
935 aKey, envValue );
936 }
937 else
938 {
939 wxLogTrace( traceEnvVars, wxS( "InitializeEnvironment: Setting entry %s to default %s" ),
940 aKey, aDefault );
941 }
942 };
943
944 addVar( ENV_VAR::GetVersionedEnvVarName( wxS( "FOOTPRINT_DIR" ) ), PATHS::GetStockFootprintsPath() );
945 addVar( ENV_VAR::GetVersionedEnvVarName( wxS( "3DMODEL_DIR" ) ), PATHS::GetStock3dmodelsPath() );
946 addVar( ENV_VAR::GetVersionedEnvVarName( wxS( "TEMPLATE_DIR" ) ), PATHS::GetStockTemplatesPath() );
947 addVar( wxT( "KICAD_USER_TEMPLATE_DIR" ), PATHS::GetUserTemplatesPath() );
948 addVar( ENV_VAR::GetVersionedEnvVarName( wxS( "3RD_PARTY" ) ), PATHS::GetDefault3rdPartyPath() );
949 addVar( ENV_VAR::GetVersionedEnvVarName( wxS( "SYMBOL_DIR" ) ), PATHS::GetStockSymbolsPath() );
950 addVar( ENV_VAR::GetVersionedEnvVarName( wxS( "DESIGN_BLOCK_DIR" ) ), PATHS::GetStockDesignBlocksPath() );
951}
952
953
955 std::vector<LEGACY_3D_SEARCH_PATH>& aSearchPaths )
956{
957 wxFileName cfgpath( path );
958
959 // This should be the same as wxWidgets 3.0 wxPATH_NORM_ALL which is deprecated in 3.1.
960 // There are known issues with environment variable expansion so maybe we should be using
961 // our own ExpandEnvVarSubstitutions() here instead.
962 cfgpath.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
963 wxString cfgname = cfgpath.GetFullPath();
964
965 std::ifstream cfgFile;
966 std::string cfgLine;
967
968 if( !wxFileName::Exists( cfgname ) )
969 {
970 std::ostringstream ostr;
971 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
972 wxString errmsg = "no 3D configuration file";
973 ostr << " * " << errmsg.ToUTF8() << " '";
974 ostr << cfgname.ToUTF8() << "'";
975 wxLogTrace( traceSettings, "%s\n", ostr.str().c_str() );
976 return false;
977 }
978
979 cfgFile.open( cfgname.ToUTF8() );
980
981 if( !cfgFile.is_open() )
982 {
983 std::ostringstream ostr;
984 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
985 wxString errmsg = wxS( "Could not open configuration file" );
986 ostr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'";
987 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
988 return false;
989 }
990
991 int lineno = 0;
993 size_t idx;
994 int vnum = 0; // version number
995
996 while( cfgFile.good() )
997 {
998 cfgLine.clear();
999 std::getline( cfgFile, cfgLine );
1000 ++lineno;
1001
1002 if( cfgLine.empty() )
1003 {
1004 if( cfgFile.eof() )
1005 break;
1006
1007 continue;
1008 }
1009
1010 if( 1 == lineno && cfgLine.compare( 0, 2, "#V" ) == 0 )
1011 {
1012 // extract the version number and parse accordingly
1013 if( cfgLine.size() > 2 )
1014 {
1015 std::istringstream istr;
1016 istr.str( cfgLine.substr( 2 ) );
1017 istr >> vnum;
1018 }
1019
1020 continue;
1021 }
1022
1023 idx = 0;
1024
1025 if( !getLegacy3DHollerith( cfgLine, idx, al.m_Alias ) )
1026 continue;
1027
1028 // Don't add KICADn_3DMODEL_DIR, one of its legacy equivalents, or KIPRJMOD from a
1029 // config file. They're system variables which are defined at runtime.
1030 wxString versionedPath = wxString::Format( wxS( "${%s}" ),
1031 ENV_VAR::GetVersionedEnvVarName( wxS( "3DMODEL_DIR" ) ) );
1032
1033 if( al.m_Alias == versionedPath
1034 || al.m_Alias == wxS( "${KIPRJMOD}" )
1035 || al.m_Alias == wxS( "$(KIPRJMOD)" )
1036 || al.m_Alias == wxS( "${KISYS3DMOD}" )
1037 || al.m_Alias == wxS( "$(KISYS3DMOD)" ) )
1038 {
1039 continue;
1040 }
1041
1042 if( !getLegacy3DHollerith( cfgLine, idx, al.m_Pathvar ) )
1043 continue;
1044
1045 if( !getLegacy3DHollerith( cfgLine, idx, al.m_Description ) )
1046 continue;
1047
1048 aSearchPaths.push_back( al );
1049 }
1050
1051 cfgFile.close();
1052
1053 return true;
1054}
1055
1056
1057bool COMMON_SETTINGS::getLegacy3DHollerith( const std::string& aString, size_t& aIndex, wxString& aResult )
1058{
1059 aResult.clear();
1060
1061 if( aIndex >= aString.size() )
1062 {
1063 std::ostringstream ostr;
1064 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
1065 wxString errmsg = wxS( "bad Hollerith string on line" );
1066 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
1067 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
1068
1069 return false;
1070 }
1071
1072 size_t i2 = aString.find( '"', aIndex );
1073
1074 if( std::string::npos == i2 )
1075 {
1076 std::ostringstream ostr;
1077 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
1078 wxString errmsg = wxS( "missing opening quote mark in config file" );
1079 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
1080 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
1081
1082 return false;
1083 }
1084
1085 ++i2;
1086
1087 if( i2 >= aString.size() )
1088 {
1089 std::ostringstream ostr;
1090 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
1091 wxString errmsg = wxS( "invalid entry (unexpected end of line)" );
1092 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
1093 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
1094
1095 return false;
1096 }
1097
1098 std::string tnum;
1099
1100 while( aString[i2] >= '0' && aString[i2] <= '9' )
1101 tnum.append( 1, aString[i2++] );
1102
1103 if( tnum.empty() || aString[i2++] != ':' )
1104 {
1105 std::ostringstream ostr;
1106 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
1107 wxString errmsg = wxS( "bad Hollerith string on line" );
1108 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
1109 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
1110
1111 return false;
1112 }
1113
1114 std::istringstream istr;
1115 istr.str( tnum );
1116 size_t nchars;
1117 istr >> nchars;
1118
1119 if( ( i2 + nchars ) >= aString.size() )
1120 {
1121 std::ostringstream ostr;
1122 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
1123 wxString errmsg = wxS( "invalid entry (unexpected end of line)" );
1124 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
1125 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
1126
1127 return false;
1128 }
1129
1130 if( nchars > 0 )
1131 {
1132 aResult = wxString::FromUTF8( aString.substr( i2, nchars ).c_str() );
1133 i2 += nchars;
1134 }
1135
1136 if( i2 >= aString.size() || aString[i2] != '"' )
1137 {
1138 std::ostringstream ostr;
1139 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
1140 wxString errmsg = wxS( "missing closing quote mark in config file" );
1141 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
1142 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
1143
1144 return false;
1145 }
1146
1147 aIndex = i2 + 1;
1148 return true;
1149}
int index
SPACEMOUSE m_SpaceMouse
std::unique_ptr< COMMON_SETTINGS_INTERNALS > m_csInternals
APPEARANCE m_Appearance
virtual ~COMMON_SETTINGS()
static bool getLegacy3DHollerith(const std::string &aString, size_t &aIndex, wxString &aResult)
bool readLegacy3DResolverCfg(const wxString &aPath, std::vector< LEGACY_3D_SEARCH_PATH > &aSearchPaths)
PACKAGE_MANAGER m_PackageManager
void InitializeEnvironment()
Creates the built-in environment variables and sets their default values.
AUTO_BACKUP m_Backup
TEMPLATES m_FieldNameTemplates
Global field name templates shared by all project editors.
DO_NOT_SHOW_AGAIN m_DoNotShowAgain
virtual bool MigrateFromLegacy(wxConfigBase *aLegacyConfig) override
Migrates from wxConfig to JSON-based configuration.
@ GAL_TYPE_OPENGL
OpenGL implementation.
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.
bool fromLegacy(wxConfigBase *aConfig, const std::string &aKey, const std::string &aDest)
Translates a legacy wxConfig 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...
bool Contains(const std::string &aPath) const
std::optional< ValueType > Get(const std::string &aPath) const
Fetches a value from within the JSON document.
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
JSON_SETTINGS(const wxString &aFilename, SETTINGS_LOC aLocation, int aSchemaVersion)
std::unique_ptr< JSON_SETTINGS_INTERNALS > m_internals
Stores an enum as an integer.
Definition parameters.h:232
Like a normal param, but with custom getter and setter functions.
Definition parameters.h:299
static wxString GetStockSymbolsPath()
Gets the stock (install) symbols path.
Definition paths.cpp:262
static wxString GetUserTemplatesPath()
Gets the user path for custom templates.
Definition paths.cpp:71
static wxString GetDefault3rdPartyPath()
Gets the default path for PCM packages.
Definition paths.cpp:126
static wxString GetStock3dmodelsPath()
Gets the stock (install) 3dmodels path.
Definition paths.cpp:295
static wxString GetStockTemplatesPath()
Gets the stock (install) templates path.
Definition paths.cpp:317
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
Definition paths.cpp:586
static wxString GetStockDesignBlocksPath()
Gets the stock (install) footprints path.
Definition paths.cpp:284
static wxString GetStockFootprintsPath()
Gets the stock (install) footprints path.
Definition paths.cpp:273
Implement an OUTPUTFORMATTER to a memory buffer.
Definition richio.h:430
const std::string & GetString()
Definition richio.h:453
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
@ ZIP
Zip archive snapshots; autosave uses recovery files.
@ INCREMENTAL
Git-based local history (default)
TOUCHPAD_MODE
@ USER_DIR
Under the KiCad user data directory.
@ PROJECT_DIR
Inside the project directory (default)
Functions related to environment variables, including help functions.
const wxChar *const traceEnvVars
Flag to enable debug output of environment variable operations.
#define ALLOW_EXCEPTIONS
#define IGNORE_COMMENTS
template KICOMMON_API void JSON_SETTINGS::Set< std::string >(const std::string &aPath, std::string aValue)
SETTINGS_LOC
@ USER
The main config directory (e.g. ~/.config/kicad/)
#define traceSettings
KICOMMON_API wxString GetVersionedEnvVarName(const wxString &aBaseName)
Construct a versioned environment variable based on this KiCad major version.
Definition env_vars.cpp:78
STL namespace.
System directories search utilities.
std::string path
wxLogTrace helper definitions.
#define FN_NORMALIZE_FLAGS
Default flags to pass to wxFileName::Normalize().
Definition wx_filename.h:35