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 <jon@craftyjon.com>
5  * Copyright (C) 2020-2021 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>
23 #include <settings/parameters.h>
24 #include <wx/config.h>
25 #include <wx/log.h>
26 
27 
29 const std::set<wxString> envVarBlacklist =
30  {
31  wxT( "KICAD6_SYMBOL_DIR" ),
32  wxT( "KICAD6_FOOTPRINT_DIR" ),
33  wxT( "KICAD6_TEMPLATES_DIR" ),
34  wxT( "KICAD6_3DMODEL_DIR" )
35  };
36 
37 
39 const int commonSchemaVersion = 2;
40 
43  m_Appearance(),
44  m_Backup(),
45  m_Env(),
46  m_Input(),
47  m_Graphics(),
48  m_Session(),
49  m_System(),
50  m_NetclassPanel()
51 {
52  // This only effect the first time KiCad is run. The user's setting will be used for all
53  // subsequent runs.
54  // Menu icons are off by default on OSX and on for all other platforms.
55  // Use automatic canvas scaling on OSX, but not on the other platforms (their detection
56  // isn't as good).
57 #if defined( __WXMAC__ )
58  bool defaultUseIconsInMenus = false;
59  double canvasScale = 0.0;
60 #else
61  bool defaultUseIconsInMenus = true;
62  double canvasScale = 1.0;
63 #endif
64 
65  m_params.emplace_back( new PARAM<double>( "appearance.canvas_scale",
66  &m_Appearance.canvas_scale, canvasScale ) );
67 
68  m_params.emplace_back( new PARAM<int>( "appearance.icon_scale",
69  &m_Appearance.icon_scale, 0 ) );
70 
71  m_params.emplace_back( new PARAM<bool>( "appearance.use_icons_in_menus",
72  &m_Appearance.use_icons_in_menus, defaultUseIconsInMenus ) );
73 
74  m_params.emplace_back( new PARAM<bool>( "auto_backup.enabled", &m_Backup.enabled, true ) );
75 
76  m_params.emplace_back( new PARAM<bool>( "auto_backup.backup_on_autosave",
77  &m_Backup.backup_on_autosave, false ) );
78 
79  m_params.emplace_back( new PARAM<int>( "auto_backup.limit_total_files",
80  &m_Backup.limit_total_files, 25 ) );
81 
82  m_params.emplace_back( new PARAM<unsigned long long>( "auto_backup.limit_total_size",
83  &m_Backup.limit_total_size, 104857600 ) );
84 
85  m_params.emplace_back( new PARAM<int>( "auto_backup.limit_daily_files",
87 
88  m_params.emplace_back( new PARAM<int>( "auto_backup.min_interval",
89  &m_Backup.min_interval, 300 ) );
90 
91  m_params.emplace_back( new PARAM<bool>( "environment.show_warning_dialog",
92  &m_Env.show_warning_dialog, false ) );
93 
94  m_params.emplace_back( new PARAM_MAP<wxString>( "environment.vars", &m_Env.vars, {} ) );
95 
96  m_params.emplace_back( new PARAM<bool>( "input.auto_pan", &m_Input.auto_pan, false ) );
97 
98  m_params.emplace_back( new PARAM<int>( "input.auto_pan_acceleration",
100 
101  m_params.emplace_back( new PARAM<bool>( "input.center_on_zoom",
102  &m_Input.center_on_zoom, true ) );
103 
104  m_params.emplace_back( new PARAM<bool>( "input.immediate_actions",
105  &m_Input.immediate_actions, true ) );
106 
107  m_params.emplace_back( new PARAM<bool>( "input.warp_mouse_on_move",
108  &m_Input.warp_mouse_on_move, true ) );
109 
110  m_params.emplace_back( new PARAM<bool>( "input.horizontal_pan",
111  &m_Input.horizontal_pan, false ) );
112 
113 #if defined(__WXMAC__) || defined(__WXGTK3__)
114  bool default_zoom_acceleration = false;
115 #else
116  bool default_zoom_acceleration = true;
117 #endif
118 
119  m_params.emplace_back( new PARAM<bool>( "input.zoom_acceleration",
120  &m_Input.zoom_acceleration, default_zoom_acceleration ) );
121 
122 #ifdef __WXMAC__
123  int default_zoom_speed = 5;
124 #else
125  int default_zoom_speed = 1;
126 #endif
127 
128  m_params.emplace_back( new PARAM<int>( "input.zoom_speed",
129  &m_Input.zoom_speed, default_zoom_speed ) );
130 
131  m_params.emplace_back( new PARAM<bool>( "input.zoom_speed_auto",
132  &m_Input.zoom_speed_auto, true ) );
133 
134  m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_zoom",
136 
137  m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_pan_h",
138  &m_Input.scroll_modifier_pan_h, WXK_CONTROL ) );
139 
140  m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_pan_v",
141  &m_Input.scroll_modifier_pan_v, WXK_SHIFT ) );
142 
143  m_params.emplace_back( new PARAM_ENUM<MOUSE_DRAG_ACTION>( "input.mouse_left",
146 
147  m_params.emplace_back( new PARAM_ENUM<MOUSE_DRAG_ACTION>( "input.mouse_middle",
150 
151  m_params.emplace_back( new PARAM_ENUM<MOUSE_DRAG_ACTION>( "input.mouse_right",
154 
155  m_params.emplace_back( new PARAM<int>( "graphics.opengl_antialiasing_mode",
156  &m_Graphics.opengl_aa_mode, 0, 0, 4 ) );
157 
158  m_params.emplace_back( new PARAM<int>( "graphics.cairo_antialiasing_mode",
159  &m_Graphics.cairo_aa_mode, 0, 0, 3 ) );
160 
161  m_params.emplace_back( new PARAM<int>( "system.autosave_interval",
162  &m_System.autosave_interval, 600 ) );
163 
164  m_params.emplace_back( new PARAM<wxString>( "system.editor_name",
165  &m_System.editor_name, "" ) );
166 
167  m_params.emplace_back( new PARAM<int>( "system.file_history_size",
168  &m_System.file_history_size, 9 ) );
169 
170  m_params.emplace_back( new PARAM<wxString>( "system.language",
171  &m_System.language, "Default" ) );
172 
173  m_params.emplace_back( new PARAM<wxString>( "system.pdf_viewer_name",
174  &m_System.pdf_viewer_name, "" ) );
175 
176  m_params.emplace_back( new PARAM<bool>( "system.use_system_pdf_viewer",
177  &m_System.use_system_pdf_viewer, true ) );
178 
179  m_params.emplace_back( new PARAM<wxString>( "system.working_dir",
180  &m_System.working_dir, "" ) );
181 
182  m_params.emplace_back( new PARAM<int>( "system.clear_3d_cache_interval",
184 
185  m_params.emplace_back( new PARAM<bool>( "session.remember_open_files",
186  &m_Session.remember_open_files, false ) );
187 
188  m_params.emplace_back( new PARAM<int>( "netclass_panel.sash_pos",
189  &m_NetclassPanel.sash_pos, 160 ) );
190 
191  registerMigration( 0, 1, std::bind( &COMMON_SETTINGS::migrateSchema0to1, this ) );
192  registerMigration( 1, 2, std::bind( &COMMON_SETTINGS::migrateSchema1to2, this ) );
193 }
194 
195 
197 {
204  nlohmann::json::json_pointer mwp_pointer( "/input/mousewheel_pan"_json_pointer );
205 
206  bool mwp = false;
207 
208  try
209  {
210  mwp = at( mwp_pointer );
211  at( nlohmann::json::json_pointer( "/input"_json_pointer ) ).erase( "mousewheel_pan" );
212  }
213  catch( ... )
214  {
215  wxLogTrace( traceSettings, "COMMON_SETTINGS::Migrate 0->1: mousewheel_pan not found" );
216  }
217 
218  if( mwp )
219  {
220  ( *this )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = true;
221 
222  ( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_SHIFT;
223  ( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = 0;
224  ( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = WXK_CONTROL;
225  }
226  else
227  {
228  ( *this )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = false;
229 
230  ( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_CONTROL;
231  ( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = WXK_SHIFT;
232  ( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = 0;
233  }
234 
235  return true;
236 }
237 
238 
240 {
241  nlohmann::json::json_pointer v1_pointer( "/input/prefer_select_to_drag"_json_pointer );
242 
243  bool prefer_selection = false;
244 
245  try
246  {
247  prefer_selection = at( v1_pointer );
248  at( nlohmann::json::json_pointer( "/input"_json_pointer ) ).erase( "prefer_select_to_drag" );
249  }
250  catch( ... )
251  {
252  wxLogTrace( traceSettings, "COMMON_SETTINGS::Migrate 1->2: prefer_select_to_drag not found" );
253  }
254 
255  if( prefer_selection )
256  ( *this )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::SELECT;
257  else
258  ( *this )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::DRAG_ANY;
259 
260  return true;
261 }
262 
263 
264 bool COMMON_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
265 {
266  bool ret = true;
267 
268  ret &= fromLegacy<double>( aCfg, "CanvasScale", "appearance.canvas_scale" );
269  ret &= fromLegacy<int>( aCfg, "IconScale", "appearance.icon_scale" );
270  ret &= fromLegacy<bool>( aCfg, "UseIconsInMenus", "appearance.use_icons_in_menus" );
271 
272 // Force OSX to automatically scale the canvas. Before v6, the user setting wasn't used on OSX
273 // and was set to 1.0. In v6, the setting is now used by OSX and should default to automatic
274 // scaling.
275 #ifdef __WXMAC__
276  ( *this )[PointerFromString( "appearance.canvas_scale" )] = 0.0;
277 #endif
278 
279  ret &= fromLegacy<bool>( aCfg, "ShowEnvVarWarningDialog", "environment.show_warning_dialog" );
280 
281  auto load_env_vars = [&] () {
282  wxString key, value;
283  long index = 0;
284  nlohmann::json::json_pointer ptr = PointerFromString( "environment.vars" );
285 
286  aCfg->SetPath( "EnvironmentVariables" );
287  ( *this )[ptr] = nlohmann::json( {} );
288 
289  while( aCfg->GetNextEntry( key, index ) )
290  {
291  if( envVarBlacklist.count( key ) )
292  {
293  wxLogTrace( traceSettings, "Migrate Env: %s is blacklisted; skipping.", key );
294  continue;
295  }
296 
297  value = aCfg->Read( key, wxEmptyString );
298 
299  if( !value.IsEmpty() )
300  {
301  ptr.push_back( key.ToStdString() );
302 
303  wxLogTrace( traceSettings, "Migrate Env: %s=%s", ptr.to_string(), value );
304  ( *this )[ptr] = value.ToUTF8();
305 
306  ptr.pop_back();
307  }
308  }
309 
310  aCfg->SetPath( ".." );
311  };
312 
313  load_env_vars();
314 
315  bool mousewheel_pan = false;
316 
317  if( aCfg->Read( "MousewheelPAN", &mousewheel_pan ) && mousewheel_pan )
318  {
319  ( *this )[PointerFromString( "input.horizontal_pan" )] = true;
320 
321  ( *this )[PointerFromString( "input.scroll_modifier_pan_h" )] = WXK_SHIFT;
322  ( *this )[PointerFromString( "input.scroll_modifier_pan_v" )] = 0;
323  ( *this )[PointerFromString( "input.scroll_modifier_zoom" )] = WXK_CONTROL;
324  }
325 
326  ret &= fromLegacy<bool>( aCfg, "AutoPAN", "input.auto_pan" );
327  ret &= fromLegacy<bool>( aCfg, "ImmediateActions", "input.immediate_actions" );
328  ret &= fromLegacy<bool>( aCfg, "PreferSelectionToDragging", "input.prefer_select_to_drag" );
329  ret &= fromLegacy<bool>( aCfg, "MoveWarpsCursor", "input.warp_mouse_on_move" );
330  ret &= fromLegacy<bool>( aCfg, "ZoomNoCenter", "input.center_on_zoom" );
331 
332  // This was stored inverted in legacy config
333  if( ret )
334  {
335  auto p = PointerFromString( "input.center_on_zoom" );
336  ( *this )[p] = !( *this )[p];
337  }
338 
339  ret &= fromLegacy<int>( aCfg, "OpenGLAntialiasingMode", "graphics.opengl_antialiasing_mode" );
340  ret &= fromLegacy<int>( aCfg, "CairoAntialiasingMode", "graphics.cairo_antialiasing_mode" );
341 
342  ret &= fromLegacy<int>( aCfg, "AutoSaveInterval", "system.autosave_interval" );
343  ret &= fromLegacyString( aCfg, "Editor", "system.editor_name" );
344  ret &= fromLegacy<int>( aCfg, "FileHistorySize", "system.file_history_size" );
345  ret &= fromLegacyString( aCfg, "LanguageID", "system.language" );
346  ret &= fromLegacyString( aCfg, "PdfBrowserName", "system.pdf_viewer_name" );
347  ret &= fromLegacy<bool>( aCfg, "UseSystemBrowser", "system.use_system_pdf_viewer" );
348  ret &= fromLegacyString( aCfg, "WorkingDir", "system.working_dir" );
349 
350  return ret;
351 }
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
unsigned long long limit_total_size
Maximum total size of backups (bytes), 0 for unlimited.
MOUSE_DRAG_ACTION drag_left
Represents a map of <std::string, Value>.
Definition: parameters.h:643
const int commonSchemaVersion
! Update the schema version whenever a migration is required
bool enabled
Automatically back up the project when files are saved.
SETTINGS_LOC
Definition: json_settings.h:44
AUTO_BACKUP m_Backup
APPEARANCE m_Appearance
Stores an enum as an integer.
Definition: parameters.h:226
virtual bool MigrateFromLegacy(wxConfigBase *aLegacyConfig) override
Migrates from wxConfig to JSON-based configuration.
nlohmann::json json
Definition: gerbview.cpp:40
MOUSE_DRAG_ACTION drag_right
NETCLASS_PANEL m_NetclassPanel
std::map< std::string, wxString > vars
ENVIRONMENT m_Env
int min_interval
Minimum time, in seconds, between subsequent backups.
bool fromLegacyString(wxConfigBase *aConfig, const std::string &aKey, const std::string &aDest)
Translates a legacy wxConfig string value to a given JSON pointer value.
void registerMigration(int aOldSchemaVersion, int aNewSchemaVersion, std::function< bool(void)> aMigrator)
Registers a migration from one schema version to another.
const std::set< wxString > envVarBlacklist
! The following environment variables will never be migrated from a previous version
The main config directory (e.g. ~/.config/kicad/)
bool backup_on_autosave
Trigger a backup on autosave.
int limit_daily_files
Maximum files to keep per day, 0 for unlimited.
const wxChar *const traceSettings
Flag to enable debug output of settings operations and management.
static nlohmann::json::json_pointer PointerFromString(std::string aPath)
Builds a JSON pointer based on a given string.
MOUSE_DRAG_ACTION drag_middle
int limit_total_files
Maximum number of backup archives to retain.