KiCad PCB EDA Suite
app_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
22#include <common.h>
23#include <eda_units.h>
24#include <layer_ids.h>
25#include <pgm_base.h>
29#include <settings/parameters.h>
30
31
32APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaVersion ) :
33 JSON_SETTINGS( aFilename, SETTINGS_LOC::USER, aSchemaVersion ),
34 m_CrossProbing(),
35 m_FindReplace(),
36 m_Graphics(),
37 m_ColorPicker(),
38 m_LibTree(),
39 m_Printing(),
40 m_System(),
41 m_Window(),
42 m_appSettingsSchemaVersion( aSchemaVersion )
43{
44 // Make Coverity happy:
46
47 // Build parameters list:
48 m_params.emplace_back(
49 new PARAM<int>( "find_replace.match_mode", &m_FindReplace.match_mode, 0 ) );
50
51 m_params.emplace_back(
52 new PARAM<bool>( "find_replace.match_case", &m_FindReplace.match_case, false ) );
53
54 m_params.emplace_back( new PARAM<bool>( "find_replace.search_and_replace",
56
57 m_params.emplace_back( new PARAM<wxString>( "find_replace.find_string",
58 &m_FindReplace.find_string, wxS( "" ) ) );
59
60 m_params.emplace_back( new PARAM_LIST<wxString>( "find_replace.find_history",
62
63 m_params.emplace_back( new PARAM<wxString>( "find_replace.replace_string",
65
66 m_params.emplace_back( new PARAM_LIST<wxString>( "find_replace.replace_history",
68
69 m_params.emplace_back( new PARAM<int>( "graphics.canvas_type",
71
72 m_params.emplace_back( new PARAM<float>( "graphics.highlight_factor",
73 &m_Graphics.highlight_factor, 0.5f, 0.0, 1.0f ) );
74
75 m_params.emplace_back( new PARAM<float>( "graphics.select_factor",
76 &m_Graphics.select_factor, 0.75f, 0.0, 1.0f ) );
77
78 m_params.emplace_back( new PARAM<int>( "color_picker.default_tab",
80
81 m_params.emplace_back( new PARAM_LIST<wxString>( "lib_tree.columns", &m_LibTree.columns, {} ) );
82
83 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "lib_tree.column_widths",
84 [&]() -> nlohmann::json
85 {
86 nlohmann::json ret = {};
87
88 for( const std::pair<const wxString, int>& pair : m_LibTree.column_widths )
89 ret[std::string( pair.first.ToUTF8() )] = pair.second;
90
91 return ret;
92 },
93 [&]( const nlohmann::json& aJson )
94 {
95 if( !aJson.is_object() )
96 return;
97
99
100 for( const auto& entry : aJson.items() )
101 {
102 if( !entry.value().is_number_integer() )
103 continue;
104
105 m_LibTree.column_widths[ entry.key() ] = entry.value().get<int>();
106 }
107 },
108 {} ) );
109
110 m_params.emplace_back( new PARAM<bool>( "printing.background",
111 &m_Printing.background, false ) );
112
113 m_params.emplace_back( new PARAM<bool>( "printing.monochrome",
114 &m_Printing.monochrome, true ) );
115
116 m_params.emplace_back( new PARAM<double>( "printing.scale",
117 &m_Printing.scale, 1.0 ) );
118
119 m_params.emplace_back( new PARAM<bool>( "printing.use_theme",
120 &m_Printing.use_theme, false ) );
121
122 m_params.emplace_back( new PARAM<wxString>( "printing.color_theme",
123 &m_Printing.color_theme, wxS( "" ) ) );
124
125 m_params.emplace_back( new PARAM<bool>( "printing.title_block",
126 &m_Printing.title_block, false ) );
127
128 m_params.emplace_back( new PARAM_LIST<int>( "printing.layers",
129 &m_Printing.layers, {} ) );
130
131 m_params.emplace_back( new PARAM<bool>( "system.first_run_shown",
132 &m_System.first_run_shown, false ) ); //@todo RFB remove? - not used
133
134 m_params.emplace_back( new PARAM<int>( "system.max_undo_items",
135 &m_System.max_undo_items, 0 ) );
136
137 m_params.emplace_back( new PARAM_LIST<wxString>( "system.file_history",
138 &m_System.file_history, {} ) );
139
140 m_params.emplace_back( new PARAM<int>( "system.units",
141 &m_System.units, static_cast<int>( EDA_UNITS::MILLIMETRES ) ) );
142
143 m_params.emplace_back( new PARAM<int>( "system.last_metric_units",
144 &m_System.last_metric_units, static_cast<int>( EDA_UNITS::MILLIMETRES ) ) );
145
146 m_params.emplace_back( new PARAM<int>( "system.last_imperial_units",
147 &m_System.last_imperial_units, static_cast<int>( EDA_UNITS::INCHES ) ) );
148
149 m_params.emplace_back( new PARAM<wxString>( "appearance.color_theme",
150 &m_ColorTheme, wxS( "_builtin_default" ) ) );
151
152 addParamsForWindow( &m_Window, "window" );
153
154 m_params.emplace_back( new PARAM<bool>( "cross_probing.on_selection",
155 &m_CrossProbing.on_selection, true ) );
156
157 m_params.emplace_back( new PARAM<bool>( "cross_probing.center_on_items",
159
160 m_params.emplace_back( new PARAM<bool>( "cross_probing.zoom_to_fit",
161 &m_CrossProbing.zoom_to_fit, true ) );
162
163 m_params.emplace_back( new PARAM<bool>( "cross_probing.auto_highlight",
165}
166
167
168bool APP_SETTINGS_BASE::MigrateFromLegacy( wxConfigBase* aCfg )
169{
170 bool ret = true;
171
172 const std::string f = getLegacyFrameName();
173
174 ret &= fromLegacyString( aCfg, "LastFindString", "find_replace.find_string" );
175 ret &= fromLegacyString( aCfg, "LastReplaceString", "find_replace.replace_string" );
176
177 migrateFindReplace( aCfg );
178
179 ret &= fromLegacy<int>( aCfg, "canvas_type", "graphics.canvas_type" );
180
181 ret &= fromLegacy<int>( aCfg, "P22LIB_TREE_MODEL_ADAPTERSelectorColumnWidth",
182 "lib_tree.column_width" );
183
184 ret &= fromLegacy<bool>( aCfg, "PrintMonochrome", "printing.monochrome" );
185 ret &= fromLegacy<double>( aCfg, "PrintScale", "printing.scale" );
186 ret &= fromLegacy<bool>( aCfg, "PrintPageFrame", "printing.title_block" );
187
188 {
189 nlohmann::json js = nlohmann::json::array();
190 wxString key;
191 bool val = false;
192
193 for( unsigned i = 0; i < PCB_LAYER_ID_COUNT; ++i )
194 {
195 key.Printf( wxT( "PlotLayer_%d" ), i );
196
197 if( aCfg->Read( key, &val ) && val )
198 js.push_back( i );
199 }
200
201 Set( "printing.layers", js );
202 }
203
204 ret &= fromLegacy<bool>( aCfg, f + "FirstRunShown", "system.first_run_shown" );
205 ret &= fromLegacy<int>( aCfg, f + "DevelMaxUndoItems", "system.max_undo_items" );
206 ret &= fromLegacy<int>( aCfg, f + "Units", "system.units" );
207
208 {
209 int max_history_size = Pgm().GetCommonSettings()->m_System.file_history_size;
210 wxString file, key;
211 nlohmann::json js = nlohmann::json::array();
212
213 for( int i = 1; i <= max_history_size; i++ )
214 {
215 key.Printf( "file%d", i );
216 file = aCfg->Read( key, wxEmptyString );
217
218 if( !file.IsEmpty() )
219 js.push_back( file.ToStdString() );
220 }
221
222 Set( "system.file_history", js );
223 }
224
225 ret &= migrateWindowConfig( aCfg, f, "window" );
226
227 return ret;
228}
229
230
232{
233 const int find_replace_history_size = 10;
234 nlohmann::json find_history = nlohmann::json::array();
235 nlohmann::json replace_history = nlohmann::json::array();
236 wxString tmp, find_key, replace_key;
237
238 for( int i = 0; i < find_replace_history_size; ++i )
239 {
240 find_key.Printf( "FindStringHistoryList%d", i );
241 replace_key.Printf( "ReplaceStringHistoryList%d", i );
242
243 if( aCfg->Read( find_key, &tmp ) )
244 find_history.push_back( tmp.ToStdString() );
245
246 if( aCfg->Read( replace_key, &tmp ) )
247 replace_history.push_back( tmp.ToStdString() );
248 }
249
250 Set( "find_replace.find_history", find_history );
251 Set( "find_replace.replace_history", replace_history );
252}
253
254
255bool APP_SETTINGS_BASE::migrateWindowConfig( wxConfigBase* aCfg, const std::string& aFrame,
256 const std::string& aJsonPath )
257{
258 bool ret = true;
259
260 const std::string frameGDO = aFrame + "GalDisplayOptions";
261 const std::string cursorPath = aJsonPath + ".cursor";
262 const std::string gridPath = aJsonPath + ".grid";
263
264 ret &= fromLegacy<bool>( aCfg, aFrame + "Maximized", aJsonPath + ".maximized" );
265 ret &= fromLegacyString( aCfg, aFrame + "MostRecentlyUsedPath", aJsonPath + ".mru_path" );
266 ret &= fromLegacy<int>( aCfg, aFrame + "Size_x", aJsonPath + ".size_x" );
267 ret &= fromLegacy<int>( aCfg, aFrame + "Size_y", aJsonPath + ".size_y" );
268 ret &= fromLegacyString( aCfg, aFrame + "Perspective", aJsonPath + ".perspective" );
269 ret &= fromLegacy<int>( aCfg, aFrame + "Pos_x", aJsonPath + ".pos_x" );
270 ret &= fromLegacy<int>( aCfg, aFrame + "Pos_y", aJsonPath + ".pos_y" );
271
272 ret &= fromLegacy<bool>( aCfg, frameGDO + "ForceDisplayCursor", cursorPath + ".always_show_cursor" );
273 ret &= fromLegacy<bool>( aCfg, frameGDO + "CursorFullscreen", cursorPath + ".fullscreen_cursor" );
274
275 ret &= fromLegacy<int>( aCfg, aFrame + "_LastGridSize", gridPath + ".last_size" );
276
277 ret &= fromLegacy<int>( aCfg, aFrame + "FastGrid1", gridPath + ".fast_grid_1" );
278 ret &= fromLegacy<int>( aCfg, aFrame + "FastGrid2", gridPath + ".fast_grid_2" );
279
280 ret &= fromLegacy<bool>( aCfg, frameGDO + "GridAxesEnabled", gridPath + ".axes_enabled" );
281 ret &= fromLegacy<double>( aCfg, frameGDO + "GridLineWidth", gridPath + ".line_width" );
282 ret &= fromLegacy<double>( aCfg, frameGDO + "GridMaxDensity", gridPath + ".min_spacing" );
283 ret &= fromLegacy<bool>( aCfg, frameGDO + "ShowGrid", gridPath + ".show" );
284 ret &= fromLegacy<int>( aCfg, frameGDO + "GridStyle", gridPath + ".style" );
285 ret &= fromLegacyColor( aCfg, frameGDO + "GridColor", gridPath + ".color" );
286
287 return ret;
288}
289
290
291void APP_SETTINGS_BASE::addParamsForWindow( WINDOW_SETTINGS* aWindow, const std::string& aJsonPath )
292{
293 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".maximized",
294 &aWindow->state.maximized, false ) );
295
296 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".mru_path",
297 &aWindow->mru_path, wxS( "" ) ) );
298
299 m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_x", &aWindow->state.size_x, 0 ) );
300
301 m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_y", &aWindow->state.size_y, 0 ) );
302
303 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".perspective",
304 &aWindow->perspective, wxS( "" ) ) );
305
306 m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_x", &aWindow->state.pos_x, 0 ) );
307
308 m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_y", &aWindow->state.pos_y, 0 ) );
309
310 m_params.emplace_back( new PARAM<unsigned int>( aJsonPath + ".display", &aWindow->state.display, 0 ) );
311
312 m_params.emplace_back( new PARAM_LIST<double>( aJsonPath + ".zoom_factors",
313 &aWindow->zoom_factors, {} ) );
314
315 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".grid.axes_enabled",
316 &aWindow->grid.axes_enabled, false ) );
317
318 int defaultGridIdx;
319
320 if( m_filename == wxS( "pl_editor" ) )
321 {
322 defaultGridIdx = 1;
323
324 m_params.emplace_back( new PARAM_LIST<wxString>( aJsonPath + ".grid.sizes",
325 &aWindow->grid.sizes, DefaultGridSizeList() ) );
326 }
327 else if( m_filename == wxS( "eeschema" ) || m_filename == wxS( "symbol_editor" ) )
328 {
329 defaultGridIdx = 1;
330
331 // Eeschema's grids are fixed to keep wires/pins connected
332 }
333 else
334 {
335 defaultGridIdx = 4;
336
337 m_params.emplace_back( new PARAM_LIST<wxString>( aJsonPath + ".grid.sizes",
338 &aWindow->grid.sizes, DefaultGridSizeList() ) );
339 }
340
341 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.last_size",
342 &aWindow->grid.last_size_idx, defaultGridIdx ) );
343
344 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.fast_grid_1",
345 &aWindow->grid.fast_grid_1, defaultGridIdx ) );
346
347 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.fast_grid_2",
348 &aWindow->grid.fast_grid_2, defaultGridIdx + 1 ) );
349
350 // for grid user, use a default value compatible with eeschema and pcbnew (10 mils)
351 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".grid.user_grid_x",
352 &aWindow->grid.user_grid_x, "10 mil" ) );
353 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".grid.user_grid_y",
354 &aWindow->grid.user_grid_y, "10 mil" ) );
355
356 m_params.emplace_back( new PARAM<double>( aJsonPath + ".grid.line_width",
357 &aWindow->grid.line_width, 1.0 ) );
358
359 m_params.emplace_back( new PARAM<double>( aJsonPath + ".grid.min_spacing",
360 &aWindow->grid.min_spacing, 10 ) );
361
362 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".grid.show",
363 &aWindow->grid.show, true ) );
364
365 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.style",
366 &aWindow->grid.style, 0 ) );
367
368 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.snap",
369 &aWindow->grid.snap, 0 ) );
370
371 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".cursor.always_show_cursor",
372 &aWindow->cursor.always_show_cursor, true ) );
373
374 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".cursor.fullscreen_cursor",
375 &aWindow->cursor.fullscreen_cursor, false ) );
376}
377
378
379const std::vector<wxString> APP_SETTINGS_BASE::DefaultGridSizeList() const
380{
381 if( m_filename == wxS( "eeschema" ) || m_filename == wxS( "symbol_editor" ) )
382 {
383 return { wxS( "100 mil" ),
384 wxS( "50 mil" ),
385 wxS( "25 mil" ),
386 wxS( "10 mil" ),
387 wxS( "5 mil" ),
388 wxS( "2 mil" ),
389 wxS( "1 mil" ) };
390 }
391 else
392 {
393 return { wxS( "1000 mil" ),
394 wxS( "500 mil" ),
395 wxS( "250 mil" ),
396 wxS( "200 mil" ),
397 wxS( "100 mil" ),
398 wxS( "50 mil" ),
399 wxS( "25 mil" ),
400 wxS( "20 mil" ),
401 wxS( "10 mil" ),
402 wxS( "5 mil" ),
403 wxS( "2 mil" ),
404 wxS( "1 mil" ),
405 wxS( "5.0 mm" ),
406 wxS( "2.5 mm" ),
407 wxS( "1.0 mm" ),
408 wxS( "0.5 mm" ),
409 wxS( "0.25 mm" ),
410 wxS( "0.2 mm" ),
411 wxS( "0.1 mm" ),
412 wxS( "0.05 mm" ),
413 wxS( "0.025 mm" ),
414 wxS( "0.01 mm" ) };
415 }
416}
417
418
420{
421 // We used to store only the width of the first column, because there were only
422 // two possible columns.
423 if( std::optional<int> optWidth = Get<int>( "lib_tree.column_width" ) )
424 {
425 Set<nlohmann::json>( "lib_tree.column_widths", { { "Item", *optWidth } } );
426 At( "lib_tree" ).erase( "column_width" );
427 }
428
429 return true;
430}
WINDOW_SETTINGS m_Window
Definition: app_settings.h:187
APP_SETTINGS_BASE(const std::string &aFilename, int aSchemaVersion)
FIND_REPLACE m_FindReplace
Definition: app_settings.h:175
bool migrateWindowConfig(wxConfigBase *aCfg, const std::string &aFrameName, const std::string &aJsonPath)
Migrates legacy window settings into the JSON document.
void migrateFindReplace(wxConfigBase *aCfg)
! Migrates the find/replace history string lists
const std::vector< wxString > DefaultGridSizeList() const
COLOR_PICKER m_ColorPicker
Definition: app_settings.h:179
virtual std::string getLegacyFrameName() const
Definition: app_settings.h:197
virtual bool MigrateFromLegacy(wxConfigBase *aCfg) override
Migrates from wxConfig to JSON-based configuration.
wxString m_ColorTheme
Active color theme name.
Definition: app_settings.h:190
CROSS_PROBING_SETTINGS m_CrossProbing
Definition: app_settings.h:173
void addParamsForWindow(WINDOW_SETTINGS *aWindow, const std::string &aJsonPath)
Adds parameters for the given window object.
bool migrateLibTreeWidth()
Migrates the library tree width setting from a single column (Item) to multi-column.
@ GAL_TYPE_OPENGL
OpenGL implementation.
bool fromLegacyString(wxConfigBase *aConfig, const std::string &aKey, const std::string &aDest)
Translates a legacy wxConfig string value to a given JSON pointer value.
wxString m_filename
The filename (not including path) of this settings file (inicode)
bool fromLegacyColor(wxConfigBase *aConfig, const std::string &aKey, const std::string &aDest)
Translates a legacy COLOR4D stored in a wxConfig string to a given JSON pointer value.
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
nlohmann::json & At(const std::string &aPath)
Wrappers for the underlying JSON API so that most consumers don't need json.hpp All of these function...
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...
The common library.
nlohmann::json json
Definition: gerbview.cpp:44
SETTINGS_LOC
Definition: json_settings.h:47
@ USER
The main config directory (e.g. ~/.config/kicad/)
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:137
see class PGM_BASE
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
std::vector< wxString > replace_history
Definition: app_settings.h:117
std::vector< wxString > find_history
Definition: app_settings.h:115
float highlight_factor
How much to brighten highlighted objects by.
Definition: app_settings.h:128
float select_factor
How much to brighten selected objects by.
Definition: app_settings.h:129
std::vector< wxString > columns
Ordered list of visible columns in the tree.
Definition: app_settings.h:139
std::map< wxString, int > column_widths
Column widths, keyed by header name.
Definition: app_settings.h:140
bool monochrome
Whether or not to print in monochrome.
Definition: app_settings.h:146
bool background
Whether or not to print background color.
Definition: app_settings.h:145
std::vector< int > layers
List of enabled layers for printing.
Definition: app_settings.h:151
wxString color_theme
Color theme to use for printing.
Definition: app_settings.h:149
double scale
Printout scale.
Definition: app_settings.h:147
bool title_block
Whether or not to print title block.
Definition: app_settings.h:150
bool use_theme
If false, display color theme will be used.
Definition: app_settings.h:148
std::vector< wxString > file_history
Definition: app_settings.h:158
bool on_selection
Synchronize the selection for multiple items too.
Definition: app_settings.h:32
bool zoom_to_fit
Zoom to fit items (ignored if center_on_items is off)
Definition: app_settings.h:34
bool center_on_items
Automatically pan to cross-probed items.
Definition: app_settings.h:33
bool auto_highlight
Automatically turn on highlight mode in the target frame.
Definition: app_settings.h:35
bool always_show_cursor
Definition: app_settings.h:43
bool fullscreen_cursor
Definition: app_settings.h:44
wxString user_grid_x
Definition: app_settings.h:54
double line_width
Definition: app_settings.h:59
wxString user_grid_y
Definition: app_settings.h:55
double min_spacing
Definition: app_settings.h:60
std::vector< wxString > sizes
Definition: app_settings.h:53
Stores the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:92
CURSOR_SETTINGS cursor
Definition: app_settings.h:98
WINDOW_STATE state
Definition: app_settings.h:93
GRID_SETTINGS grid
Definition: app_settings.h:99
wxString mru_path
Definition: app_settings.h:94
std::vector< double > zoom_factors
Definition: app_settings.h:96
wxString perspective
Definition: app_settings.h:95
unsigned int display
Definition: app_settings.h:85