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 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 <class_draw_panel_gal.h>
22 #include <common.h>
23 #include <layer_ids.h>
24 #include <pgm_base.h>
25 #include <settings/app_settings.h>
26 #include <settings/json_settings_internals.h>
27 #include <settings/common_settings.h>
28 #include <settings/parameters.h>
29 #include <base_units.h>
30
31 ///! Update the schema version whenever a migration is required
32 const int appSettingsSchemaVersion = 0;
33
34
APP_SETTINGS_BASE(const std::string & aFilename,int aSchemaVersion)35 APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaVersion ) :
36 JSON_SETTINGS( aFilename, SETTINGS_LOC::USER, aSchemaVersion ),
37 m_CrossProbing(),
38 m_FindReplace(),
39 m_Graphics(),
40 m_ColorPicker(),
41 m_LibTree(),
42 m_Printing(),
43 m_System(),
44 m_Window(),
45 m_appSettingsSchemaVersion( aSchemaVersion )
46 {
47 // Make Coverity happy:
48 m_LibTree.column_width = 360;
49 m_Graphics.canvas_type = EDA_DRAW_PANEL_GAL::GAL_FALLBACK;
50
51 // Build parameters list:
52 m_params.emplace_back( new PARAM<int>( "find_replace.flags", &m_FindReplace.flags, 1 ) );
53
54 m_params.emplace_back( new PARAM<wxString>( "find_replace.find_string",
55 &m_FindReplace.find_string, "" ) );
56
57 m_params.emplace_back( new PARAM_LIST<wxString>( "find_replace.find_history",
58 &m_FindReplace.find_history, {} ) );
59
60 m_params.emplace_back( new PARAM<wxString>( "find_replace.replace_string",
61 &m_FindReplace.replace_string, "" ) );
62
63 m_params.emplace_back( new PARAM_LIST<wxString>( "find_replace.replace_history",
64 &m_FindReplace.replace_history, {} ) );
65
66 m_params.emplace_back( new PARAM<int>( "graphics.canvas_type",
67 &m_Graphics.canvas_type, EDA_DRAW_PANEL_GAL::GAL_FALLBACK ) );
68
69 m_params.emplace_back( new PARAM<float>(
70 "graphics.highlight_factor", &m_Graphics.highlight_factor, 0.5f, 0.0, 1.0f ) );
71
72 m_params.emplace_back( new PARAM<float>(
73 "graphics.select_factor", &m_Graphics.select_factor, 0.75f, 0.0, 1.0f ) );
74
75 m_params.emplace_back( new PARAM<float>(
76 "graphics.high_contrast_factor", &m_Graphics.high_contrast_factor, 0.35f, 0.0, 1.0f ) );
77
78 m_params.emplace_back( new PARAM<int>( "color_picker.default_tab",
79 &m_ColorPicker.default_tab, 0 ) );
80
81 m_params.emplace_back( new PARAM<int>( "lib_tree.column_width",
82 &m_LibTree.column_width, 360 ) );
83
84 // Now that we allow hiding/showing of the tree control, it's never terribly useful to
85 // decrease the width to nothing, and wxWidgets appears to have some bugs where it sets it
86 // way too narrow.
87 if( m_LibTree.column_width < 360 )
88 m_LibTree.column_width = 360;
89
90 m_params.emplace_back( new PARAM<bool>( "printing.background",
91 &m_Printing.background, false ) );
92
93 m_params.emplace_back( new PARAM<bool>( "printing.monochrome",
94 &m_Printing.monochrome, true ) );
95
96 m_params.emplace_back( new PARAM<double>( "printing.scale",
97 &m_Printing.scale, 1.0 ) );
98
99 m_params.emplace_back( new PARAM<bool>( "printing.use_theme",
100 &m_Printing.use_theme, false ) );
101
102 m_params.emplace_back( new PARAM<wxString>( "printing.color_theme",
103 &m_Printing.color_theme, "" ) );
104
105 m_params.emplace_back( new PARAM<bool>( "printing.title_block",
106 &m_Printing.title_block, false ) );
107
108 m_params.emplace_back( new PARAM_LIST<int>( "printing.layers",
109 &m_Printing.layers, {} ) );
110
111 m_params.emplace_back( new PARAM<bool>( "system.first_run_shown",
112 &m_System.first_run_shown, false ) );
113
114 m_params.emplace_back( new PARAM<int>( "system.max_undo_items",
115 &m_System.max_undo_items, 0 ) );
116
117
118 m_params.emplace_back( new PARAM_LIST<wxString>( "system.file_history",
119 &m_System.file_history, {} ) );
120
121 m_params.emplace_back( new PARAM<int>( "system.units",
122 &m_System.units, static_cast<int>( EDA_UNITS::MILLIMETRES ) ) );
123
124 m_params.emplace_back( new PARAM<int>( "system.last_metric_units",
125 &m_System.last_metric_units, static_cast<int>( EDA_UNITS::MILLIMETRES ) ) );
126
127 m_params.emplace_back( new PARAM<int>( "system.last_imperial_units",
128 &m_System.last_imperial_units, static_cast<int>( EDA_UNITS::INCHES ) ) );
129
130 m_params.emplace_back( new PARAM<wxString>( "appearance.color_theme",
131 &m_ColorTheme, "_builtin_default" ) );
132
133 addParamsForWindow( &m_Window, "window" );
134
135 m_params.emplace_back( new PARAM<bool>( "cross_probing.center_on_items",
136 &m_CrossProbing.center_on_items, true ) );
137
138 m_params.emplace_back( new PARAM<bool>( "cross_probing.zoom_to_fit",
139 &m_CrossProbing.zoom_to_fit, true ) );
140
141 m_params.emplace_back( new PARAM<bool>( "cross_probing.auto_highlight",
142 &m_CrossProbing.auto_highlight, true ) );
143 }
144
145
MigrateFromLegacy(wxConfigBase * aCfg)146 bool APP_SETTINGS_BASE::MigrateFromLegacy( wxConfigBase* aCfg )
147 {
148 bool ret = true;
149
150 const std::string f = getLegacyFrameName();
151
152 ret &= fromLegacyString( aCfg, "LastFindString", "find_replace.find_string" );
153 ret &= fromLegacyString( aCfg, "LastReplaceString", "find_replace.replace_string" );
154
155 migrateFindReplace( aCfg );
156
157 ret &= fromLegacy<int>( aCfg, "canvas_type", "graphics.canvas_type" );
158
159 ret &= fromLegacy<int>( aCfg, "P22LIB_TREE_MODEL_ADAPTERSelectorColumnWidth",
160 "lib_tree.column_width" );
161
162 ret &= fromLegacy<bool>( aCfg, "PrintMonochrome", "printing.monochrome" );
163 ret &= fromLegacy<double>( aCfg, "PrintScale", "printing.scale" );
164 ret &= fromLegacy<bool>( aCfg, "PrintPageFrame", "printing.title_block" );
165
166 {
167 nlohmann::json js = nlohmann::json::array();
168 wxString key;
169 bool val = false;
170
171 for( unsigned i = 0; i < PCB_LAYER_ID_COUNT; ++i )
172 {
173 key.Printf( wxT( "PlotLayer_%d" ), i );
174
175 if( aCfg->Read( key, &val ) && val )
176 js.push_back( i );
177 }
178
179 Set( "printing.layers", js );
180 }
181
182 ret &= fromLegacy<bool>( aCfg, f + "FirstRunShown", "system.first_run_shown" );
183 ret &= fromLegacy<int>( aCfg, f + "DevelMaxUndoItems", "system.max_undo_items" );
184 ret &= fromLegacy<int>( aCfg, f + "Units", "system.units" );
185
186 {
187 int max_history_size = Pgm().GetCommonSettings()->m_System.file_history_size;
188 wxString file, key;
189 nlohmann::json js = nlohmann::json::array();
190
191 for( int i = 1; i <= max_history_size; i++ )
192 {
193 key.Printf( "file%d", i );
194 file = aCfg->Read( key, wxEmptyString );
195
196 if( !file.IsEmpty() )
197 js.push_back( file.ToStdString() );
198 }
199
200 Set( "system.file_history", js );
201 }
202
203 ret &= migrateWindowConfig( aCfg, f, "window" );
204
205 return ret;
206 }
207
208
migrateFindReplace(wxConfigBase * aCfg)209 void APP_SETTINGS_BASE::migrateFindReplace( wxConfigBase* aCfg )
210 {
211 const int find_replace_history_size = 10;
212 nlohmann::json find_history = nlohmann::json::array();
213 nlohmann::json replace_history = nlohmann::json::array();
214 wxString tmp, find_key, replace_key;
215
216 for( int i = 0; i < find_replace_history_size; ++i )
217 {
218 find_key.Printf( "FindStringHistoryList%d", i );
219 replace_key.Printf( "ReplaceStringHistoryList%d", i );
220
221 if( aCfg->Read( find_key, &tmp ) )
222 find_history.push_back( tmp.ToStdString() );
223
224 if( aCfg->Read( replace_key, &tmp ) )
225 replace_history.push_back( tmp.ToStdString() );
226 }
227
228 Set( "find_replace.find_history", find_history );
229 Set( "find_replace.replace_history", replace_history );
230 }
231
232
migrateWindowConfig(wxConfigBase * aCfg,const std::string & aFrame,const std::string & aJsonPath)233 bool APP_SETTINGS_BASE::migrateWindowConfig( wxConfigBase* aCfg, const std::string& aFrame,
234 const std::string& aJsonPath )
235 {
236 bool ret = true;
237
238 const std::string frameGDO = aFrame + "GalDisplayOptions";
239 const std::string cursorPath = aJsonPath + ".cursor";
240 const std::string gridPath = aJsonPath + ".grid";
241
242 ret &= fromLegacy<bool>( aCfg, aFrame + "Maximized", aJsonPath + ".maximized" );
243 ret &= fromLegacyString( aCfg, aFrame + "MostRecentlyUsedPath", aJsonPath + ".mru_path" );
244 ret &= fromLegacy<int>( aCfg, aFrame + "Size_x", aJsonPath + ".size_x" );
245 ret &= fromLegacy<int>( aCfg, aFrame + "Size_y", aJsonPath + ".size_y" );
246 ret &= fromLegacyString( aCfg, aFrame + "Perspective", aJsonPath + ".perspective" );
247 ret &= fromLegacy<int>( aCfg, aFrame + "Pos_x", aJsonPath + ".pos_x" );
248 ret &= fromLegacy<int>( aCfg, aFrame + "Pos_y", aJsonPath + ".pos_y" );
249
250 ret &= fromLegacy<bool>( aCfg, frameGDO + "ForceDisplayCursor", cursorPath + ".always_show_cursor" );
251 ret &= fromLegacy<bool>( aCfg, frameGDO + "CursorFullscreen", cursorPath + ".fullscreen_cursor" );
252
253 ret &= fromLegacy<int>( aCfg, aFrame + "_LastGridSize", gridPath + ".last_size" );
254
255 ret &= fromLegacy<int>( aCfg, aFrame + "FastGrid1", gridPath + ".fast_grid_1" );
256 ret &= fromLegacy<int>( aCfg, aFrame + "FastGrid2", gridPath + ".fast_grid_2" );
257
258 ret &= fromLegacy<bool>( aCfg, frameGDO + "GridAxesEnabled", gridPath + ".axes_enabled" );
259 ret &= fromLegacy<double>( aCfg, frameGDO + "GridLineWidth", gridPath + ".line_width" );
260 ret &= fromLegacy<double>( aCfg, frameGDO + "GridMaxDensity", gridPath + ".min_spacing" );
261 ret &= fromLegacy<bool>( aCfg, frameGDO + "ShowGrid", gridPath + ".show" );
262 ret &= fromLegacy<int>( aCfg, frameGDO + "GridStyle", gridPath + ".style" );
263 ret &= fromLegacyColor( aCfg, frameGDO + "GridColor", gridPath + ".color" );
264
265 return ret;
266 }
267
268
addParamsForWindow(WINDOW_SETTINGS * aWindow,const std::string & aJsonPath)269 void APP_SETTINGS_BASE::addParamsForWindow( WINDOW_SETTINGS* aWindow, const std::string& aJsonPath )
270 {
271 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".maximized",
272 &aWindow->state.maximized, false ) );
273
274 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".mru_path",
275 &aWindow->mru_path, "" ) );
276
277 m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_x", &aWindow->state.size_x, 0 ) );
278
279 m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_y", &aWindow->state.size_y, 0 ) );
280
281 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".perspective",
282 &aWindow->perspective, "" ) );
283
284 m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_x", &aWindow->state.pos_x, 0 ) );
285
286 m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_y", &aWindow->state.pos_y, 0 ) );
287
288 m_params.emplace_back( new PARAM<unsigned int>( aJsonPath + ".display", &aWindow->state.display, 0 ) );
289
290 m_params.emplace_back( new PARAM_LIST<double>( aJsonPath + ".zoom_factors",
291 &aWindow->zoom_factors, {} ) );
292
293 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".grid.axes_enabled",
294 &aWindow->grid.axes_enabled, false ) );
295
296 m_params.emplace_back( new PARAM_LIST<wxString>( aJsonPath + ".grid.sizes",
297 &aWindow->grid.sizes, DefaultGridSizeList() ) );
298
299 int defaultGridIdx;
300
301 if( m_filename == "eeschema" || m_filename == "symbol_editor" || m_filename == "pl_editor" )
302 defaultGridIdx = 1;
303 else
304 defaultGridIdx = 4;
305
306 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.last_size",
307 &aWindow->grid.last_size_idx, defaultGridIdx ) );
308
309 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.fast_grid_1",
310 &aWindow->grid.fast_grid_1, defaultGridIdx ) );
311
312 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.fast_grid_2",
313 &aWindow->grid.fast_grid_2, defaultGridIdx + 1 ) );
314
315 // for grid user, use a default value compatible with eeschema and pcbnew (10 mils)
316 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".grid.user_grid_x",
317 &aWindow->grid.user_grid_x, "10 mil" ) );
318 m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".grid.user_grid_y",
319 &aWindow->grid.user_grid_y, "10 mil" ) );
320
321 m_params.emplace_back( new PARAM<double>( aJsonPath + ".grid.line_width",
322 &aWindow->grid.line_width, 1.0 ) );
323
324 m_params.emplace_back( new PARAM<double>( aJsonPath + ".grid.min_spacing",
325 &aWindow->grid.min_spacing, 10 ) );
326
327 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".grid.show",
328 &aWindow->grid.show, true ) );
329
330 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.style",
331 &aWindow->grid.style, 0 ) );
332
333 m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.snap",
334 &aWindow->grid.snap, 0 ) );
335
336 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".cursor.always_show_cursor",
337 &aWindow->cursor.always_show_cursor, true ) );
338
339 m_params.emplace_back( new PARAM<bool>( aJsonPath + ".cursor.fullscreen_cursor",
340 &aWindow->cursor.fullscreen_cursor, false ) );
341 }
342
343
DefaultGridSizeList() const344 const std::vector<wxString> APP_SETTINGS_BASE::DefaultGridSizeList() const
345 {
346 return { "1000 mil",
347 "500 mil",
348 "250 mil",
349 "200 mil",
350 "100 mil",
351 "50 mil",
352 "25 mil",
353 "20 mil",
354 "10 mil",
355 "5 mil",
356 "2 mil",
357 "1 mil",
358 "5.0 mm",
359 "2.5 mm",
360 "1.0 mm",
361 "0.5 mm",
362 "0.25 mm",
363 "0.2 mm",
364 "0.1 mm",
365 "0.05 mm",
366 "0.025 mm",
367 "0.01 mm" };
368 }
369