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 (C) 2020-2022 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 along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <set>
22#include <fstream>
23#include <sstream>
24
25#include <paths.h>
26#include <search_stack.h>
30#include <settings/parameters.h>
31#include <systemdirsappend.h>
32#include <trace_helpers.h>
33#include <wx/config.h>
34#include <wx/log.h>
35#include <wx/regex.h>
36
37
39const std::set<wxString> envVarBlacklist =
40 {
41 wxT( "KICAD7_SYMBOL_DIR" ),
42 wxT( "KICAD7_FOOTPRINT_DIR" ),
43 wxT( "KICAD7_TEMPLATES_DIR" ),
44 wxT( "KICAD7_3DMODEL_DIR" )
45 };
46
47
49const int commonSchemaVersion = 3;
50
53 m_Appearance(),
54 m_Backup(),
55 m_Env(),
56 m_Input(),
57 m_Graphics(),
58 m_Session(),
59 m_System(),
60 m_DoNotShowAgain(),
61 m_NetclassPanel(),
62 m_PackageManager()
63{
64 /*
65 * Automatic dark mode detection works fine on Mac.
66 */
67#if defined( __WXGTK__ ) || defined( __WXMSW__ )
68 m_params.emplace_back( new PARAM_ENUM<ICON_THEME>( "appearance.icon_theme",
69 &m_Appearance.icon_theme, ICON_THEME::AUTO, ICON_THEME::LIGHT, ICON_THEME::AUTO ) );
70#else
71 m_Appearance.icon_theme = ICON_THEME::AUTO;
72#endif
73
74 /*
75 * Automatic icon scaling works fine on Mac. It works mostly fine on MSW, but perhaps not
76 * uniformly enough to exclude the explicit controls there.
77 */
78#if defined( __WXGTK__ ) || defined( __WXMSW__ )
79 m_params.emplace_back( new PARAM<int>( "appearance.icon_scale",
81#else
83#endif
84
85 /*
86 * Automatic canvas scaling works fine on all supported platforms, so it's no longer exposed as
87 * a configuration option.
88 */
90
91 /*
92 * Menu icons are off by default on OSX and on for all other platforms.
93 */
94#ifdef __WXMAC__
95 m_params.emplace_back( new PARAM<bool>( "appearance.use_icons_in_menus",
97#else
98 m_params.emplace_back( new PARAM<bool>( "appearance.use_icons_in_menus",
100#endif
101
102 /*
103 * Font scaling hacks are only needed on GTK under wxWidgets 3.0.
104 */
106
107 m_params.emplace_back( new PARAM<bool>( "appearance.show_scrollbars",
108 &m_Appearance.show_scrollbars, false ) );
109
110 m_params.emplace_back( new PARAM<double>( "appearance.hicontrast_dimming_factor",
112
113 m_params.emplace_back( new PARAM<int>( "appearance.text_editor_zoom",
115
116 m_params.emplace_back( new PARAM<bool>( "auto_backup.enabled", &m_Backup.enabled, true ) );
117
118 m_params.emplace_back( new PARAM<bool>( "auto_backup.backup_on_autosave",
119 &m_Backup.backup_on_autosave, false ) );
120
121 m_params.emplace_back( new PARAM<int>( "auto_backup.limit_total_files",
123
124 m_params.emplace_back( new PARAM<unsigned long long>( "auto_backup.limit_total_size",
125 &m_Backup.limit_total_size, 104857600 ) );
126
127 m_params.emplace_back( new PARAM<int>( "auto_backup.limit_daily_files",
129
130 m_params.emplace_back( new PARAM<int>( "auto_backup.min_interval",
131 &m_Backup.min_interval, 300 ) );
132
133 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "environment.vars",
134 [&]() -> nlohmann::json
135 {
136 nlohmann::json ret = {};
137
138 for( const std::pair<wxString, ENV_VAR_ITEM> entry : m_Env.vars )
139 {
140 const ENV_VAR_ITEM& var = entry.second;
141
142 wxASSERT( entry.first == var.GetKey() );
143
144 // Default values are never persisted
145 if( var.IsDefault() )
146 {
147 wxLogTrace( traceEnvVars,
148 wxS( "COMMON_SETTINGS: Env var %s skipping save (default)" ),
149 var.GetKey() );
150 continue;
151 }
152
153 wxString value = var.GetValue();
154
155 // Vars that existed in JSON are persisted, but if they were overridden
156 // externally, we persist the old value (i.e. the one that was loaded from JSON)
157 if( var.GetDefinedExternally() )
158 {
159 if( var.GetDefinedInSettings() )
160 {
161 wxLogTrace( traceEnvVars,
162 wxS( "COMMON_SETTINGS: Env var %s was overridden externally, " )
163 "saving previously-loaded value %s",
164 var.GetKey(), var.GetSettingsValue() );
165 value = var.GetSettingsValue();
166 }
167 else
168 {
169 wxLogTrace( traceEnvVars,
170 wxS( "COMMON_SETTINGS: Env var %s skipping save (external)" ),
171 var.GetKey() );
172 continue;
173 }
174 }
175
176 wxLogTrace( traceEnvVars,
177 wxS( "COMMON_SETTINGS: Saving env var %s = %s" ),
178 var.GetKey(), value);
179
180 std::string key( var.GetKey().ToUTF8() );
181 ret[key] = value;
182 }
183
184 return ret;
185 },
186 [&]( const nlohmann::json& aJson )
187 {
188 if( !aJson.is_object() )
189 return;
190
191 for( const auto& entry : aJson.items() )
192 {
193 wxString key = wxString( entry.key().c_str(), wxConvUTF8 );
194 wxString val = entry.value().get<wxString>();
195
196 if( m_Env.vars.count( key ) )
197 {
198 if( m_Env.vars[key].GetDefinedExternally() )
199 {
200 wxLogTrace( traceEnvVars, wxS( "COMMON_SETTINGS: %s is defined externally" ),
201 key );
202 m_Env.vars[key].SetDefinedInSettings();
203 m_Env.vars[key].SetSettingsValue( val );
204 continue;
205 }
206 else
207 {
208 wxLogTrace( traceEnvVars, wxS( "COMMON_SETTINGS: Updating %s: %s -> %s"),
209 key, m_Env.vars[key].GetValue(), val );
210 m_Env.vars[key].SetValue( val );
211 }
212 }
213 else
214 {
215 wxLogTrace( traceEnvVars, wxS( "COMMON_SETTINGS: Loaded new var: %s = %s" ),
216 key, val );
217 m_Env.vars[key] = ENV_VAR_ITEM( key, val );
218 }
219
220 m_Env.vars[key].SetDefinedInSettings();
221 m_Env.vars[key].SetSettingsValue( val );
222 }
223 },
224 {} ) );
225
226 m_params.emplace_back( new PARAM<bool>( "input.focus_follow_sch_pcb",
227 &m_Input.focus_follow_sch_pcb, false ) );
228
229 m_params.emplace_back( new PARAM<bool>( "input.auto_pan", &m_Input.auto_pan, false ) );
230
231 m_params.emplace_back( new PARAM<int>( "input.auto_pan_acceleration",
232 &m_Input.auto_pan_acceleration, 5 ) );
233
234 m_params.emplace_back( new PARAM<bool>( "input.center_on_zoom",
235 &m_Input.center_on_zoom, true ) );
236
237 m_params.emplace_back( new PARAM<bool>( "input.immediate_actions",
238 &m_Input.immediate_actions, true ) );
239
240 m_params.emplace_back( new PARAM<bool>( "input.warp_mouse_on_move",
241 &m_Input.warp_mouse_on_move, true ) );
242
243 m_params.emplace_back( new PARAM<bool>( "input.horizontal_pan",
244 &m_Input.horizontal_pan, false ) );
245
246 m_params.emplace_back( new PARAM<bool>( "input.hotkey_feedback",
247 &m_Input.hotkey_feedback, true ) );
248
249 m_params.emplace_back( new PARAM<bool>( "input.zoom_acceleration",
250 &m_Input.zoom_acceleration, false ) );
251
252#ifdef __WXMAC__
253 int default_zoom_speed = 5;
254#else
255 int default_zoom_speed = 1;
256#endif
257
258 m_params.emplace_back( new PARAM<int>( "input.zoom_speed",
259 &m_Input.zoom_speed, default_zoom_speed ) );
260
261 m_params.emplace_back( new PARAM<bool>( "input.zoom_speed_auto",
262 &m_Input.zoom_speed_auto, true ) );
263
264 m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_zoom",
265 &m_Input.scroll_modifier_zoom, 0 ) );
266
267 m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_pan_h",
268 &m_Input.scroll_modifier_pan_h, WXK_CONTROL ) );
269
270 m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_pan_v",
271 &m_Input.scroll_modifier_pan_v, WXK_SHIFT ) );
272
273 m_params.emplace_back( new PARAM<bool>( "input.reverse_scroll_pan_h",
274 &m_Input.reverse_scroll_pan_h, false ) );
275
276 m_params.emplace_back( new PARAM_ENUM<MOUSE_DRAG_ACTION>( "input.mouse_left",
279
280 m_params.emplace_back( new PARAM_ENUM<MOUSE_DRAG_ACTION>( "input.mouse_middle",
283
284 m_params.emplace_back( new PARAM_ENUM<MOUSE_DRAG_ACTION>( "input.mouse_right",
287
288 m_params.emplace_back( new PARAM<int>( "graphics.opengl_antialiasing_mode",
289 &m_Graphics.opengl_aa_mode, 1, 0, 2 ) );
290
291 m_params.emplace_back( new PARAM<int>( "graphics.cairo_antialiasing_mode",
292 &m_Graphics.cairo_aa_mode, 0, 0, 2 ) );
293
294 m_params.emplace_back( new PARAM<int>( "system.autosave_interval",
295 &m_System.autosave_interval, 600 ) );
296
297#ifdef __WXMAC__
298 m_params.emplace_back( new PARAM<wxString>( "system.text_editor",
299 &m_System.text_editor, wxS( "/usr/bin/open -e" ) ) );
300#else
301 m_params.emplace_back( new PARAM<wxString>( "system.text_editor",
302 &m_System.text_editor, wxS( "" ) ) );
303#endif
304
305 m_params.emplace_back( new PARAM<int>( "system.file_history_size",
306 &m_System.file_history_size, 9 ) );
307
308 m_params.emplace_back( new PARAM<wxString>( "system.language",
309 &m_System.language, wxS( "Default" ) ) );
310
311 m_params.emplace_back( new PARAM<wxString>( "system.pdf_viewer_name",
312 &m_System.pdf_viewer_name, wxS( "" ) ) );
313
314 m_params.emplace_back( new PARAM<bool>( "system.use_system_pdf_viewer",
315 &m_System.use_system_pdf_viewer, true ) );
316
317 m_params.emplace_back( new PARAM<wxString>( "system.working_dir",
318 &m_System.working_dir, wxS( "" ) ) );
319
320 m_params.emplace_back( new PARAM<int>( "system.clear_3d_cache_interval",
321 &m_System.clear_3d_cache_interval, 30 ) );
322
323 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.zone_fill_warning",
324 &m_DoNotShowAgain.zone_fill_warning, false ) );
325
326 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.env_var_overwrite_warning",
327 &m_DoNotShowAgain.env_var_overwrite_warning, false ) );
328
329 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.scaled_3d_models_warning",
330 &m_DoNotShowAgain.scaled_3d_models_warning, false ) );
331
332 m_params.emplace_back( new PARAM<bool>( "do_not_show_again.data_collection_prompt",
333 &m_DoNotShowAgain.data_collection_prompt, false ) );
334
335 m_params.emplace_back( new PARAM<bool>( "session.remember_open_files",
336 &m_Session.remember_open_files, false ) );
337
338 m_params.emplace_back( new PARAM_LIST<wxString>( "session.pinned_symbol_libs",
339 &m_Session.pinned_symbol_libs, {} ) );
340
341 m_params.emplace_back( new PARAM_LIST<wxString>( "session.pinned_fp_libs",
342 &m_Session.pinned_fp_libs, {} ) );
343
344 m_params.emplace_back( new PARAM<int>( "netclass_panel.sash_pos",
345 &m_NetclassPanel.sash_pos, 160 ) );
346
347 m_params.emplace_back( new PARAM<int>( "package_manager.sash_pos",
348 &m_PackageManager.sash_pos, 380 ) );
349
350 registerMigration( 0, 1, std::bind( &COMMON_SETTINGS::migrateSchema0to1, this ) );
351 registerMigration( 1, 2, std::bind( &COMMON_SETTINGS::migrateSchema1to2, this ) );
352 registerMigration( 2, 3, std::bind( &COMMON_SETTINGS::migrateSchema2to3, this ) );
353}
354
355
357{
364 nlohmann::json::json_pointer mwp_pointer( "/input/mousewheel_pan"_json_pointer );
365
366 bool mwp = false;
367
368 try
369 {
370 mwp = m_internals->at( mwp_pointer );
371 m_internals->At( "input" ).erase( "mousewheel_pan" );
372 }
373 catch( ... )
374 {
375 wxLogTrace( traceSettings, wxT( "COMMON_SETTINGS::Migrate 0->1: mousewheel_pan not found" ) );
376 }
377
378 if( mwp )
379 {
380 ( *m_internals )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = true;
381
382 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_SHIFT;
383 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = 0;
384 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = WXK_CONTROL;
385 }
386 else
387 {
388 ( *m_internals )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = false;
389
390 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_CONTROL;
391 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = WXK_SHIFT;
392 ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = 0;
393 }
394
395 return true;
396}
397
398
400{
401 nlohmann::json::json_pointer v1_pointer( "/input/prefer_select_to_drag"_json_pointer );
402
403 bool prefer_selection = false;
404
405 try
406 {
407 prefer_selection = m_internals->at( v1_pointer );
408 m_internals->at( nlohmann::json::json_pointer( "/input"_json_pointer ) ).erase( "prefer_select_to_drag" );
409 }
410 catch( ... )
411 {
412 wxLogTrace( traceSettings, wxT( "COMMON_SETTINGS::Migrate 1->2: prefer_select_to_drag not found" ) );
413 }
414
415 if( prefer_selection )
416 ( *m_internals )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::SELECT;
417 else
418 ( *m_internals )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::DRAG_ANY;
419
420 return true;
421}
422
423
425{
426 wxFileName cfgpath;
427 cfgpath.AssignDir( SETTINGS_MANAGER::GetUserSettingsPath() );
428 cfgpath.AppendDir( wxT( "3d" ) );
429 cfgpath.SetFullName( wxS( "3Dresolver.cfg" ) );
430 cfgpath.MakeAbsolute();
431
432 std::vector<LEGACY_3D_SEARCH_PATH> legacyPaths;
433 readLegacy3DResolverCfg( cfgpath.GetFullPath(), legacyPaths );
434
435 // env variables have a limited allowed character set for names
436 wxRegEx nonValidCharsRegex( wxS( "[^A-Z0-9_]+" ), wxRE_ADVANCED );
437
438 for( const LEGACY_3D_SEARCH_PATH& path : legacyPaths )
439 {
440 wxString key = path.m_Alias;
441 const wxString& val = path.m_Pathvar;
442
443 // The 3d alias config didnt use the same naming restrictions as real env variables
444 // We need to sanitize them
445
446 // upper case only
447 key.MakeUpper();
448 // logically swap - with _
449 key.Replace( wxS( "-" ), wxS( "_" ) );
450
451 // remove any other chars
452 nonValidCharsRegex.Replace( &key, wxEmptyString );
453
454 if( !m_Env.vars.count( key ) )
455 {
456 wxLogTrace( traceEnvVars, wxS( "COMMON_SETTINGS: Loaded new var: %s = %s" ), key, val );
457 m_Env.vars[key] = ENV_VAR_ITEM( key, val );
458 }
459 }
460
461 if( cfgpath.FileExists() )
462 {
463 wxRemoveFile( cfgpath.GetFullPath() );
464 }
465
466 return true;
467}
468
469
470bool COMMON_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
471{
472 bool ret = true;
473
474 ret &= fromLegacy<double>( aCfg, "CanvasScale", "appearance.canvas_scale" );
475 ret &= fromLegacy<int>( aCfg, "IconScale", "appearance.icon_scale" );
476 ret &= fromLegacy<bool>( aCfg, "UseIconsInMenus", "appearance.use_icons_in_menus" );
477 ret &= fromLegacy<bool>( aCfg, "ShowEnvVarWarningDialog", "environment.show_warning_dialog" );
478
479 auto load_env_vars =
480 [&]()
481 {
482 wxString key, value;
483 long index = 0;
484 nlohmann::json::json_pointer ptr = m_internals->PointerFromString( "environment.vars" );
485
486 aCfg->SetPath( "EnvironmentVariables" );
487 ( *m_internals )[ptr] = nlohmann::json( {} );
488
489 while( aCfg->GetNextEntry( key, index ) )
490 {
491 if( envVarBlacklist.count( key ) )
492 {
493 wxLogTrace( traceSettings, wxT( "Migrate Env: %s is blacklisted; skipping." ), key );
494 continue;
495 }
496
497 value = aCfg->Read( key, wxEmptyString );
498
499 if( !value.IsEmpty() )
500 {
501 ptr.push_back( key.ToStdString() );
502
503 wxLogTrace( traceSettings, wxT( "Migrate Env: %s=%s" ), ptr.to_string(), value );
504 ( *m_internals )[ptr] = value.ToUTF8();
505
506 ptr.pop_back();
507 }
508 }
509
510 aCfg->SetPath( ".." );
511 };
512
513 load_env_vars();
514
515 bool mousewheel_pan = false;
516
517 if( aCfg->Read( "MousewheelPAN", &mousewheel_pan ) && mousewheel_pan )
518 {
519 Set( "input.horizontal_pan", true );
520 Set( "input.scroll_modifier_pan_h", static_cast<int>( WXK_SHIFT ) );
521 Set( "input.scroll_modifier_pan_v", 0 );
522 Set( "input.scroll_modifier_zoom", static_cast<int>( WXK_CONTROL ) );
523 }
524
525 ret &= fromLegacy<bool>( aCfg, "AutoPAN", "input.auto_pan" );
526 ret &= fromLegacy<bool>( aCfg, "ImmediateActions", "input.immediate_actions" );
527 ret &= fromLegacy<bool>( aCfg, "PreferSelectionToDragging", "input.prefer_select_to_drag" );
528 ret &= fromLegacy<bool>( aCfg, "MoveWarpsCursor", "input.warp_mouse_on_move" );
529 ret &= fromLegacy<bool>( aCfg, "ZoomNoCenter", "input.center_on_zoom" );
530
531 // This was stored inverted in legacy config
532 if( std::optional<bool> value = Get<bool>( "input.center_on_zoom" ) )
533 Set( "input.center_on_zoom", !( *value ) );
534
535 ret &= fromLegacy<int>( aCfg, "OpenGLAntialiasingMode", "graphics.opengl_antialiasing_mode" );
536 ret &= fromLegacy<int>( aCfg, "CairoAntialiasingMode", "graphics.cairo_antialiasing_mode" );
537
538 ret &= fromLegacy<int>( aCfg, "AutoSaveInterval", "system.autosave_interval" );
539 ret &= fromLegacyString( aCfg, "Editor", "system.editor_name" );
540 ret &= fromLegacy<int>( aCfg, "FileHistorySize", "system.file_history_size" );
541 ret &= fromLegacyString( aCfg, "LanguageID", "system.language" );
542 ret &= fromLegacyString( aCfg, "PdfBrowserName", "system.pdf_viewer_name" );
543 ret &= fromLegacy<bool>( aCfg, "UseSystemBrowser", "system.use_system_pdf_viewer" );
544 ret &= fromLegacyString( aCfg, "WorkingDir", "system.working_dir" );
545
546 return ret;
547}
548
549
551{
552 auto addVar =
553 [&]( const wxString& aKey, const wxString& aDefault )
554 {
555 m_Env.vars[aKey] = ENV_VAR_ITEM( aKey, aDefault, aDefault );
556
557 wxString envValue;
558
559 if( wxGetEnv( aKey, &envValue ) == true && !envValue.IsEmpty() )
560 {
561 m_Env.vars[aKey].SetValue( envValue );
562 m_Env.vars[aKey].SetDefinedExternally();
563 wxLogTrace( traceEnvVars,
564 wxS( "InitializeEnvironment: Entry %s defined externally as %s" ), aKey,
565 envValue );
566 }
567 else
568 {
569 wxLogTrace( traceEnvVars, wxS( "InitializeEnvironment: Setting entry %s to default %s" ),
570 aKey, aDefault );
571 }
572 };
573
574 wxFileName basePath( PATHS::GetStockEDALibraryPath(), wxEmptyString );
575
576 wxFileName path( basePath );
577 path.AppendDir( wxT( "footprints" ) );
578 addVar( wxT( "KICAD7_FOOTPRINT_DIR" ), path.GetFullPath() );
579
580 path = basePath;
581 path.AppendDir( wxT( "3dmodels" ) );
582 addVar( wxT( "KICAD7_3DMODEL_DIR" ), path.GetFullPath() );
583
584 addVar( wxT( "KICAD7_TEMPLATE_DIR" ), PATHS::GetStockTemplatesPath() );
585
586 addVar( wxT( "KICAD_USER_TEMPLATE_DIR" ), PATHS::GetUserTemplatesPath() );
587
588 addVar( wxT( "KICAD7_3RD_PARTY" ), PATHS::GetDefault3rdPartyPath() );
589
590 path = basePath;
591 path.AppendDir( wxT( "symbols" ) );
592 addVar( wxT( "KICAD7_SYMBOL_DIR" ), path.GetFullPath() );
593}
594
595
597 std::vector<LEGACY_3D_SEARCH_PATH>& aSearchPaths )
598{
599 wxFileName cfgpath( path );
600
601 // This should be the same as wxWidgets 3.0 wxPATH_NORM_ALL which is deprecated in 3.1.
602 // There are known issues with environment variable expansion so maybe we should be using
603 // our own ExpandEnvVarSubstitutions() here instead.
604 cfgpath.Normalize( FN_NORMALIZE_FLAGS | wxPATH_NORM_ENV_VARS );
605 wxString cfgname = cfgpath.GetFullPath();
606
607 std::ifstream cfgFile;
608 std::string cfgLine;
609
610 if( !wxFileName::Exists( cfgname ) )
611 {
612 std::ostringstream ostr;
613 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
614 wxString errmsg = "no 3D configuration file";
615 ostr << " * " << errmsg.ToUTF8() << " '";
616 ostr << cfgname.ToUTF8() << "'";
617 wxLogTrace( traceSettings, "%s\n", ostr.str().c_str() );
618 return false;
619 }
620
621 cfgFile.open( cfgname.ToUTF8() );
622
623 if( !cfgFile.is_open() )
624 {
625 std::ostringstream ostr;
626 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
627 wxString errmsg = wxS( "Could not open configuration file" );
628 ostr << " * " << errmsg.ToUTF8() << " '" << cfgname.ToUTF8() << "'";
629 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
630 return false;
631 }
632
633 int lineno = 0;
635 size_t idx;
636 int vnum = 0; // version number
637
638 while( cfgFile.good() )
639 {
640 cfgLine.clear();
641 std::getline( cfgFile, cfgLine );
642 ++lineno;
643
644 if( cfgLine.empty() )
645 {
646 if( cfgFile.eof() )
647 break;
648
649 continue;
650 }
651
652 if( 1 == lineno && cfgLine.compare( 0, 2, "#V" ) == 0 )
653 {
654 // extract the version number and parse accordingly
655 if( cfgLine.size() > 2 )
656 {
657 std::istringstream istr;
658 istr.str( cfgLine.substr( 2 ) );
659 istr >> vnum;
660 }
661
662 continue;
663 }
664
665 idx = 0;
666
667 if( !getLegacy3DHollerith( cfgLine, idx, al.m_Alias ) )
668 continue;
669
670 // Don't add KICAD7_3DMODEL_DIR, one of its legacy equivalents, or KIPRJMOD from a
671 // config file. They're system variables are are defined at runtime.
672 if( al.m_Alias == wxS( "${KICAD7_3DMODEL_DIR}" ) || al.m_Alias == wxS( "${KIPRJMOD}" )
673 || al.m_Alias == wxS( "$(KIPRJMOD)" ) || al.m_Alias == wxS( "${KISYS3DMOD}" )
674 || al.m_Alias == wxS( "$(KISYS3DMOD)" ) )
675 {
676 continue;
677 }
678
679 if( !getLegacy3DHollerith( cfgLine, idx, al.m_Pathvar ) )
680 continue;
681
682 if( !getLegacy3DHollerith( cfgLine, idx, al.m_Description ) )
683 continue;
684
685 aSearchPaths.push_back( al );
686 }
687
688 cfgFile.close();
689
690 return true;
691}
692
693
694bool COMMON_SETTINGS::getLegacy3DHollerith( const std::string& aString, size_t& aIndex,
695 wxString& aResult )
696{
697 aResult.clear();
698
699 if( aIndex >= aString.size() )
700 {
701 std::ostringstream ostr;
702 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
703 wxString errmsg = wxS( "bad Hollerith string on line" );
704 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
705 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
706
707 return false;
708 }
709
710 size_t i2 = aString.find( '"', aIndex );
711
712 if( std::string::npos == i2 )
713 {
714 std::ostringstream ostr;
715 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
716 wxString errmsg = wxS( "missing opening quote mark in config file" );
717 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
718 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
719
720 return false;
721 }
722
723 ++i2;
724
725 if( i2 >= aString.size() )
726 {
727 std::ostringstream ostr;
728 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
729 wxString errmsg = wxS( "invalid entry (unexpected end of line)" );
730 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
731 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
732
733 return false;
734 }
735
736 std::string tnum;
737
738 while( aString[i2] >= '0' && aString[i2] <= '9' )
739 tnum.append( 1, aString[i2++] );
740
741 if( tnum.empty() || aString[i2++] != ':' )
742 {
743 std::ostringstream ostr;
744 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
745 wxString errmsg = wxS( "bad Hollerith string on line" );
746 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
747 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
748
749 return false;
750 }
751
752 std::istringstream istr;
753 istr.str( tnum );
754 size_t nchars;
755 istr >> nchars;
756
757 if( ( i2 + nchars ) >= aString.size() )
758 {
759 std::ostringstream ostr;
760 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
761 wxString errmsg = wxS( "invalid entry (unexpected end of line)" );
762 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
763 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
764
765 return false;
766 }
767
768 if( nchars > 0 )
769 {
770 aResult = wxString::FromUTF8( aString.substr( i2, nchars ).c_str() );
771 i2 += nchars;
772 }
773
774 if( i2 >= aString.size() || aString[i2] != '"' )
775 {
776 std::ostringstream ostr;
777 ostr << __FILE__ << ": " << __FUNCTION__ << ": " << __LINE__ << "\n";
778 wxString errmsg = wxS( "missing closing quote mark in config file" );
779 ostr << " * " << errmsg.ToUTF8() << "\n'" << aString << "'";
780 wxLogTrace( traceSettings, wxS( "%s\n" ), ostr.str().c_str() );
781
782 return false;
783 }
784
785 aIndex = i2 + 1;
786 return true;
787}
APPEARANCE m_Appearance
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.
AUTO_BACKUP m_Backup
virtual bool MigrateFromLegacy(wxConfigBase *aLegacyConfig) override
Migrates from wxConfig to JSON-based configuration.
ENVIRONMENT m_Env
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.
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
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::unique_ptr< JSON_SETTINGS_INTERNALS > m_internals
Stores an enum as an integer.
Definition: parameters.h:217
Like a normal param, but with custom getter and setter functions.
Definition: parameters.h:282
static wxString GetUserTemplatesPath()
Gets the user path for custom templates.
Definition: paths.cpp:86
static wxString GetStockEDALibraryPath()
Gets the stock (install) EDA library data path, which is the base path for templates,...
Definition: paths.cpp:186
static wxString GetDefault3rdPartyPath()
Gets the default path for PCM packages.
Definition: paths.cpp:129
static wxString GetStockTemplatesPath()
Gets the stock (install) templates path.
Definition: paths.cpp:242
static wxString GetUserSettingsPath()
Return the user configuration path used to store KiCad's configuration files.
const std::set< wxString > envVarBlacklist
! The following environment variables will never be migrated from a previous version
const int commonSchemaVersion
! Update the schema version whenever a migration is required
const wxChar *const traceEnvVars
Flag to enable debug output of environment variable operations.
const wxChar *const traceSettings
Flag to enable debug output of settings operations and management.
SETTINGS_LOC
Definition: json_settings.h:47
@ USER
The main config directory (e.g. ~/.config/kicad/)
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().
Definition: wx_filename.h:39