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