KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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>
30#include <settings/parameters.h>
31
32
33APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaVersion ) :
34 JSON_SETTINGS( aFilename, SETTINGS_LOC::USER, aSchemaVersion ),
35 m_CrossProbing(),
36 m_FindReplace(),
37 m_Graphics(),
38 m_ColorPicker(),
39 m_LibTree(),
40 m_Printing(),
41 m_System(),
42 m_Window(),
43 m_appSettingsSchemaVersion( aSchemaVersion )
44{
45 // Make Coverity happy:
47
48 // Build parameters list:
49 m_params.emplace_back(
50 new PARAM<int>( "find_replace.match_mode", &m_FindReplace.match_mode, 0 ) );
51
52 m_params.emplace_back(
53 new PARAM<bool>( "find_replace.match_case", &m_FindReplace.match_case, false ) );
54
55 m_params.emplace_back( new PARAM<bool>( "find_replace.search_and_replace",
57
58 m_params.emplace_back( new PARAM<wxString>( "find_replace.find_string",
59 &m_FindReplace.find_string, wxS( "" ) ) );
60
61 m_params.emplace_back( new PARAM_LIST<wxString>( "find_replace.find_history",
63
64 m_params.emplace_back( new PARAM<wxString>( "find_replace.replace_string",
66
67 m_params.emplace_back( new PARAM_LIST<wxString>( "find_replace.replace_history",
69
70 m_params.emplace_back( new PARAM<int>( "graphics.canvas_type",
72
73 m_params.emplace_back( new PARAM<float>( "graphics.highlight_factor",
74 &m_Graphics.highlight_factor, 0.5f, 0.0, 1.0f ) );
75
76 m_params.emplace_back( new PARAM<float>( "graphics.select_factor",
77 &m_Graphics.select_factor, 0.75f, 0.0, 1.0f ) );
78
79 m_params.emplace_back( new PARAM<int>( "color_picker.default_tab",
81
82 m_params.emplace_back( new PARAM_LIST<wxString>( "lib_tree.columns", &m_LibTree.columns, {} ) );
83
84 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "lib_tree.column_widths",
85 [&]() -> nlohmann::json
86 {
87 nlohmann::json ret = {};
88
89 for( const std::pair<const wxString, int>& pair : m_LibTree.column_widths )
90 ret[std::string( pair.first.ToUTF8() )] = pair.second;
91
92 return ret;
93 },
94 [&]( const nlohmann::json& aJson )
95 {
96 if( !aJson.is_object() )
97 return;
98
100
101 for( const auto& entry : aJson.items() )
102 {
103 if( !entry.value().is_number_integer() )
104 continue;
105
106 m_LibTree.column_widths[ entry.key() ] = entry.value().get<int>();
107 }
108 },
109 {} ) );
110
111 m_params.emplace_back( new PARAM<bool>( "printing.background",
112 &m_Printing.background, false ) );
113
114 m_params.emplace_back( new PARAM<bool>( "printing.monochrome",
115 &m_Printing.monochrome, true ) );
116
117 m_params.emplace_back( new PARAM<double>( "printing.scale",
118 &m_Printing.scale, 1.0 ) );
119
120 m_params.emplace_back( new PARAM<bool>( "printing.use_theme",
121 &m_Printing.use_theme, false ) );
122
123 m_params.emplace_back( new PARAM<wxString>( "printing.color_theme",
124 &m_Printing.color_theme, wxS( "" ) ) );
125
126 m_params.emplace_back( new PARAM<bool>( "printing.title_block",
127 &m_Printing.title_block, false ) );
128
129 m_params.emplace_back( new PARAM_LIST<int>( "printing.layers",
130 &m_Printing.layers, {} ) );
131
132 m_params.emplace_back( new PARAM<bool>( "system.first_run_shown",
133 &m_System.first_run_shown, false ) ); //@todo RFB remove? - not used
134
135 m_params.emplace_back( new PARAM<int>( "system.max_undo_items",
136 &m_System.max_undo_items, 0 ) );
137
138 m_params.emplace_back( new PARAM_LIST<wxString>( "system.file_history",
139 &m_System.file_history, {} ) );
140
141 m_params.emplace_back( new PARAM<int>( "system.units",
142 &m_System.units, static_cast<int>( EDA_UNITS::MILLIMETRES ) ) );
143
144 m_params.emplace_back( new PARAM<int>( "system.last_metric_units",
145 &m_System.last_metric_units, static_cast<int>( EDA_UNITS::MILLIMETRES ) ) );
146
147 m_params.emplace_back( new PARAM<int>( "system.last_imperial_units",
148 &m_System.last_imperial_units, static_cast<int>( EDA_UNITS::INCHES ) ) );
149
150 m_params.emplace_back( new PARAM<wxString>( "appearance.color_theme",
152
153 addParamsForWindow( &m_Window, "window" );
154
155 m_params.emplace_back( new PARAM<bool>( "cross_probing.on_selection",
156 &m_CrossProbing.on_selection, true ) );
157
158 m_params.emplace_back( new PARAM<bool>( "cross_probing.center_on_items",
160
161 m_params.emplace_back( new PARAM<bool>( "cross_probing.zoom_to_fit",
162 &m_CrossProbing.zoom_to_fit, true ) );
163
164 m_params.emplace_back( new PARAM<bool>( "cross_probing.auto_highlight",
166}
167
168
169bool APP_SETTINGS_BASE::MigrateFromLegacy( wxConfigBase* aCfg )
170{
171 bool ret = true;
172
173 const std::string f = getLegacyFrameName();
174
175 ret &= fromLegacyString( aCfg, "LastFindString", "find_replace.find_string" );
176 ret &= fromLegacyString( aCfg, "LastReplaceString", "find_replace.replace_string" );
177
178 migrateFindReplace( aCfg );
179
180 ret &= fromLegacy<int>( aCfg, "canvas_type", "graphics.canvas_type" );
181
182 ret &= fromLegacy<int>( aCfg, "P22LIB_TREE_MODEL_ADAPTERSelectorColumnWidth",
183 "lib_tree.column_width" );
184
185 ret &= fromLegacy<bool>( aCfg, "PrintMonochrome", "printing.monochrome" );
186 ret &= fromLegacy<double>( aCfg, "PrintScale", "printing.scale" );
187 ret &= fromLegacy<bool>( aCfg, "PrintPageFrame", "printing.title_block" );
188
189 {
190 nlohmann::json js = nlohmann::json::array();
191 wxString key;
192 bool val = false;
193
194 for( unsigned i = 0; i < PCB_LAYER_ID_COUNT; ++i )
195 {
196 key.Printf( wxT( "PlotLayer_%d" ), i );
197
198 if( aCfg->Read( key, &val ) && val )
199 js.push_back( i );
200 }
201
202 Set( "printing.layers", js );
203 }
204
205 ret &= fromLegacy<bool>( aCfg, f + "FirstRunShown", "system.first_run_shown" );
206 ret &= fromLegacy<int>( aCfg, f + "DevelMaxUndoItems", "system.max_undo_items" );
207 ret &= fromLegacy<int>( aCfg, f + "Units", "system.units" );
208
209 {
210 int max_history_size = Pgm().GetCommonSettings()->m_System.file_history_size;
211 wxString file, key;
212 nlohmann::json js = nlohmann::json::array();
213
214 for( int i = 1; i <= max_history_size; i++ )
215 {
216 key.Printf( "file%d", i );
217 file = aCfg->Read( key, wxEmptyString );
218
219 if( !file.IsEmpty() )
220 js.push_back( file.ToStdString() );
221 }
222
223 Set( "system.file_history", js );
224 }
225
226 ret &= migrateWindowConfig( aCfg, f, "window" );
227
228 return ret;
229}
230
231
233{
234 const int find_replace_history_size = 10;
235 nlohmann::json find_history = nlohmann::json::array();
236 nlohmann::json replace_history = nlohmann::json::array();
237 wxString tmp, find_key, replace_key;
238
239 for( int i = 0; i < find_replace_history_size; ++i )
240 {
241 find_key.Printf( "FindStringHistoryList%d", i );
242 replace_key.Printf( "ReplaceStringHistoryList%d", i );
243
244 if( aCfg->Read( find_key, &tmp ) )
245 find_history.push_back( tmp.ToStdString() );
246
247 if( aCfg->Read( replace_key, &tmp ) )
248 replace_history.push_back( tmp.ToStdString() );
249 }
250
251 Set( "find_replace.find_history", find_history );
252 Set( "find_replace.replace_history", replace_history );
253}
254
255
256bool APP_SETTINGS_BASE::migrateWindowConfig( wxConfigBase* aCfg, const std::string& aFrame,
257 const std::string& aJsonPath )
258{
259 bool ret = true;
260
261 const std::string frameGDO = aFrame + "GalDisplayOptions";
262 const std::string cursorPath = aJsonPath + ".cursor";
263 const std::string gridPath = aJsonPath + ".grid";
264
265 ret &= fromLegacy<bool>( aCfg, aFrame + "Maximized", aJsonPath + ".maximized" );
266 ret &= fromLegacyString( aCfg, aFrame + "MostRecentlyUsedPath", aJsonPath + ".mru_path" );
267 ret &= fromLegacy<int>( aCfg, aFrame + "Size_x", aJsonPath + ".size_x" );
268 ret &= fromLegacy<int>( aCfg, aFrame + "Size_y", aJsonPath + ".size_y" );
269 ret &= fromLegacyString( aCfg, aFrame + "Perspective", aJsonPath + ".perspective" );
270 ret &= fromLegacy<int>( aCfg, aFrame + "Pos_x", aJsonPath + ".pos_x" );
271 ret &= fromLegacy<int>( aCfg, aFrame + "Pos_y", aJsonPath + ".pos_y" );
272
273 ret &= fromLegacy<bool>( aCfg, frameGDO + "ForceDisplayCursor", cursorPath + ".always_show_cursor" );
274 ret &= fromLegacy<bool>( aCfg, frameGDO + "CursorFullscreen", cursorPath + ".fullscreen_cursor" );
275
276 ret &= fromLegacy<int>( aCfg, aFrame + "_LastGridSize", gridPath + ".last_size" );
277
278 ret &= fromLegacy<int>( aCfg, aFrame + "FastGrid1", gridPath + ".fast_grid_1" );
279 ret &= fromLegacy<int>( aCfg, aFrame + "FastGrid2", gridPath + ".fast_grid_2" );
280
281 ret &= fromLegacy<bool>( aCfg, frameGDO + "GridAxesEnabled", gridPath + ".axes_enabled" );
282 ret &= fromLegacy<double>( aCfg, frameGDO + "GridLineWidth", gridPath + ".line_width" );
283 ret &= fromLegacy<double>( aCfg, frameGDO + "GridMaxDensity", gridPath + ".min_spacing" );
284 ret &= fromLegacy<bool>( aCfg, frameGDO + "ShowGrid", gridPath + ".show" );
285 ret &= fromLegacy<int>( aCfg, frameGDO + "GridStyle", gridPath + ".style" );
286 ret &= fromLegacyColor( aCfg, frameGDO + "GridColor", gridPath + ".color" );
287
288 return ret;
289}
290
291
292void APP_SETTINGS_BASE::addParamsForWindow( WINDOW_SETTINGS* aWindow, const std::string& aJsonPath )
293{
294 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".maximized",
295 &aWindow->state.maximized, false ) );
296
297 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".mru_path",
298 &aWindow->mru_path, wxS( "" ) ) );
299
300 m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_x", &aWindow->state.size_x, 0 ) );
301
302 m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_y", &aWindow->state.size_y, 0 ) );
303
304 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".perspective",
305 &aWindow->perspective, wxS( "" ) ) );
306
307 m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_x", &aWindow->state.pos_x, 0 ) );
308
309 m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_y", &aWindow->state.pos_y, 0 ) );
310
311 m_params.emplace_back( new PARAM<unsigned int>( aJsonPath + ".display", &aWindow->state.display, 0 ) );
312
313 m_params.emplace_back( new PARAM_LIST<double>( aJsonPath + ".zoom_factors",
314 &aWindow->zoom_factors, {} ) );
315
316 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".grid.axes_enabled",
317 &aWindow->grid.axes_enabled, false ) );
318
319 int defaultGridIdx;
320
321 if( m_filename == wxS( "pl_editor" ) )
322 {
323 defaultGridIdx = 1;
324
325 m_params.emplace_back( new PARAM_LIST<wxString>( aJsonPath + ".grid.sizes",
326 &aWindow->grid.sizes, DefaultGridSizeList() ) );
327 }
328 else if( m_filename == wxS( "eeschema" ) || m_filename == wxS( "symbol_editor" ) )
329 {
330 defaultGridIdx = 1;
331
332 // Eeschema's grids are fixed to keep wires/pins connected
333 }
334 else
335 {
336 defaultGridIdx = 4;
337
338 m_params.emplace_back( new PARAM_LIST<wxString>( aJsonPath + ".grid.sizes",
339 &aWindow->grid.sizes, DefaultGridSizeList() ) );
340 }
341
342 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.last_size",
343 &aWindow->grid.last_size_idx, defaultGridIdx ) );
344
345 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.fast_grid_1",
346 &aWindow->grid.fast_grid_1, defaultGridIdx ) );
347
348 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.fast_grid_2",
349 &aWindow->grid.fast_grid_2, defaultGridIdx + 1 ) );
350
351 // for grid user, use a default value compatible with eeschema and pcbnew (10 mils)
352 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".grid.user_grid_x",
353 &aWindow->grid.user_grid_x, "10 mil" ) );
354 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".grid.user_grid_y",
355 &aWindow->grid.user_grid_y, "10 mil" ) );
356
357 m_params.emplace_back( new PARAM<double>( aJsonPath + ".grid.line_width",
358 &aWindow->grid.line_width, 1.0 ) );
359
360 m_params.emplace_back( new PARAM<double>( aJsonPath + ".grid.min_spacing",
361 &aWindow->grid.min_spacing, 10 ) );
362
363 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".grid.show",
364 &aWindow->grid.show, true ) );
365
366 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.style",
367 &aWindow->grid.style, 0 ) );
368
369 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.snap",
370 &aWindow->grid.snap, 0 ) );
371
372 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".cursor.always_show_cursor",
373 &aWindow->cursor.always_show_cursor, true ) );
374
375 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".cursor.fullscreen_cursor",
376 &aWindow->cursor.fullscreen_cursor, false ) );
377}
378
379
380const std::vector<wxString> APP_SETTINGS_BASE::DefaultGridSizeList() const
381{
382 if( m_filename == wxS( "eeschema" ) || m_filename == wxS( "symbol_editor" ) )
383 {
384 return { wxS( "100 mil" ),
385 wxS( "50 mil" ),
386 wxS( "25 mil" ),
387 wxS( "10 mil" ),
388 wxS( "5 mil" ),
389 wxS( "2 mil" ),
390 wxS( "1 mil" ) };
391 }
392 else
393 {
394 return { wxS( "1000 mil" ),
395 wxS( "500 mil" ),
396 wxS( "250 mil" ),
397 wxS( "200 mil" ),
398 wxS( "100 mil" ),
399 wxS( "50 mil" ),
400 wxS( "25 mil" ),
401 wxS( "20 mil" ),
402 wxS( "10 mil" ),
403 wxS( "5 mil" ),
404 wxS( "2 mil" ),
405 wxS( "1 mil" ),
406 wxS( "5.0 mm" ),
407 wxS( "2.5 mm" ),
408 wxS( "1.0 mm" ),
409 wxS( "0.5 mm" ),
410 wxS( "0.25 mm" ),
411 wxS( "0.2 mm" ),
412 wxS( "0.1 mm" ),
413 wxS( "0.05 mm" ),
414 wxS( "0.025 mm" ),
415 wxS( "0.01 mm" ) };
416 }
417}
418
419
421{
422 // We used to store only the width of the first column, because there were only
423 // two possible columns.
424 if( std::optional<int> optWidth = Get<int>( "lib_tree.column_width" ) )
425 {
426 Set<nlohmann::json>( "lib_tree.column_widths", { { "Item", *optWidth } } );
427 At( "lib_tree" ).erase( "column_width" );
428 }
429
430 return true;
431}
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.
static const wxString COLOR_BUILTIN_DEFAULT
@ 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...
Like a normal param, but with custom getter and setter functions.
Definition: parameters.h:282
The common library.
template void JSON_SETTINGS::Set< nlohmann::json >(const std::string &aPath, nlohmann::json aValue)
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:115
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