KiCad PCB EDA Suite
Loading...
Searching...
No Matches
project_local_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 CERN
5 * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Jon Evans <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <lset.h>
23#include <project.h>
26#include <settings/parameters.h>
27
29
30
31PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxString& aFilename ) :
33 /* aCreateIfMissing = */ true, /* aCreateIfDefault = */ false,
34 /* aWriteFile = */ true ),
35 m_ActiveLayer( UNDEFINED_LAYER ),
36 m_ContrastModeDisplay( HIGH_CONTRAST_MODE::NORMAL ),
37 m_NetColorMode( NET_COLOR_MODE::RATSNEST ),
38 m_AutoTrackWidth( true ),
39 m_ZoneDisplayMode( ZONE_DISPLAY_MODE::SHOW_FILLED ),
40 m_TrackOpacity( 1.0 ),
41 m_ViaOpacity( 1.0 ),
42 m_PadOpacity( 1.0 ),
43 m_ZoneOpacity( 0.6 ),
44 m_ShapeOpacity( 1.0 ),
45 m_ImageOpacity( 0.6 ),
46 m_PcbSelectionFilter(),
47 m_project( aProject )
48{
49 // Keep old files around
51
52 m_params.emplace_back( new PARAM_LAMBDA<std::string>( "board.visible_layers",
53 [&]() -> std::string
54 {
55 return m_VisibleLayers.FmtHex();
56 },
57 [&]( const std::string& aString )
58 {
59 m_VisibleLayers.ParseHex( aString.c_str(), aString.size() );
60 },
62
63 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "board.visible_items",
64 [&]() -> nlohmann::json
65 {
66 nlohmann::json ret = nlohmann::json::array();
67
68 for( size_t i = 0; i < m_VisibleItems.size(); i++ )
69 if( m_VisibleItems.test( i ) )
70 ret.push_back( i );
71
72 return ret;
73 },
74 [&]( const nlohmann::json& aVal )
75 {
76 if( !aVal.is_array() || aVal.empty() )
77 {
79 return;
80 }
81
82 m_VisibleItems.reset();
83
84 for( const nlohmann::json& entry : aVal )
85 {
86 try
87 {
88 int i = entry.get<int>();
90 }
91 catch( ... )
92 {
93 // Non-integer or out of range entry in the array; ignore
94 }
95 }
96 },
97 {} ) );
98
99 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "board.selection_filter",
100 [&]() -> nlohmann::json
101 {
102 nlohmann::json ret;
103
104 ret["lockedItems"] = m_PcbSelectionFilter.lockedItems;
105 ret["footprints"] = m_PcbSelectionFilter.footprints;
106 ret["text"] = m_PcbSelectionFilter.text;
107 ret["tracks"] = m_PcbSelectionFilter.tracks;
108 ret["vias"] = m_PcbSelectionFilter.vias;
109 ret["pads"] = m_PcbSelectionFilter.pads;
110 ret["graphics"] = m_PcbSelectionFilter.graphics;
111 ret["zones"] = m_PcbSelectionFilter.zones;
112 ret["keepouts"] = m_PcbSelectionFilter.keepouts;
113 ret["dimensions"] = m_PcbSelectionFilter.dimensions;
114 ret["otherItems"] = m_PcbSelectionFilter.otherItems;
115
116 return ret;
117 },
118 [&]( const nlohmann::json& aVal )
119 {
120 if( aVal.empty() || !aVal.is_object() )
121 return;
122
123 SetIfPresent( aVal, "lockedItems", m_PcbSelectionFilter.lockedItems );
124 SetIfPresent( aVal, "footprints", m_PcbSelectionFilter.footprints );
125 SetIfPresent( aVal, "text", m_PcbSelectionFilter.text );
126 SetIfPresent( aVal, "tracks", m_PcbSelectionFilter.tracks );
127 SetIfPresent( aVal, "vias", m_PcbSelectionFilter.vias );
128 SetIfPresent( aVal, "pads", m_PcbSelectionFilter.pads );
129 SetIfPresent( aVal, "graphics", m_PcbSelectionFilter.graphics );
130 SetIfPresent( aVal, "zones", m_PcbSelectionFilter.zones );
131 SetIfPresent( aVal, "keepouts", m_PcbSelectionFilter.keepouts );
132 SetIfPresent( aVal, "dimensions", m_PcbSelectionFilter.dimensions );
133 SetIfPresent( aVal, "otherItems", m_PcbSelectionFilter.otherItems );
134 },
135 {
136 { "lockedItems", false },
137 { "footprints", true },
138 { "text", true },
139 { "tracks", true },
140 { "vias", true },
141 { "pads", true },
142 { "graphics", true },
143 { "zones", true },
144 { "keepouts", true },
145 { "dimensions", true },
146 { "otherItems", true }
147 } ) );
148
149 m_params.emplace_back( new PARAM_ENUM<PCB_LAYER_ID>( "board.active_layer",
151
152 m_params.emplace_back( new PARAM<wxString>( "board.active_layer_preset",
153 &m_ActiveLayerPreset, "" ) );
154
155 m_params.emplace_back( new PARAM_ENUM<HIGH_CONTRAST_MODE>( "board.high_contrast_mode",
156 &m_ContrastModeDisplay, HIGH_CONTRAST_MODE::NORMAL,
157 HIGH_CONTRAST_MODE::NORMAL, HIGH_CONTRAST_MODE::HIDDEN ) );
158
159 m_params.emplace_back( new PARAM<double>( "board.opacity.tracks", &m_TrackOpacity, 1.0 ) );
160 m_params.emplace_back( new PARAM<double>( "board.opacity.vias", &m_ViaOpacity, 1.0 ) );
161 m_params.emplace_back( new PARAM<double>( "board.opacity.pads", &m_PadOpacity, 1.0 ) );
162 m_params.emplace_back( new PARAM<double>( "board.opacity.zones", &m_ZoneOpacity, 0.6 ) );
163 m_params.emplace_back( new PARAM<double>( "board.opacity.images", &m_ImageOpacity, 0.6 ) );
164 m_params.emplace_back( new PARAM<double>( "board.opacity.shapes", &m_ShapeOpacity, 1.0 ) );
165
166 m_params.emplace_back( new PARAM_LIST<wxString>( "board.hidden_nets", &m_HiddenNets, {} ) );
167
168 m_params.emplace_back( new PARAM_SET<wxString>( "board.hidden_netclasses",
169 &m_HiddenNetclasses, {} ) );
170
171 m_params.emplace_back( new PARAM_ENUM<NET_COLOR_MODE>( "board.net_color_mode",
172 &m_NetColorMode, NET_COLOR_MODE::RATSNEST, NET_COLOR_MODE::OFF,
173 NET_COLOR_MODE::ALL ) );
174
175 m_params.emplace_back( new PARAM<bool>( "board.auto_track_width",
176 &m_AutoTrackWidth, true ) );
177
178 m_params.emplace_back( new PARAM_ENUM<ZONE_DISPLAY_MODE>( "board.zone_display_mode",
180 ZONE_DISPLAY_MODE::SHOW_FILLED, ZONE_DISPLAY_MODE::SHOW_FILLED,
181 ZONE_DISPLAY_MODE::SHOW_TRIANGULATION ) );
182
183 m_params.emplace_back( new PARAM<wxString>( "git.repo_username",
184 &m_GitRepoUsername, "" ) );
185
186 m_params.emplace_back( new PARAM<wxString>( "git.repo_password",
187 &m_GitRepoPassword, "" ) );
188
189 m_params.emplace_back( new PARAM<wxString>( "git.repo_type",
190 &m_GitRepoType, "" ) );
191
192 m_params.emplace_back( new PARAM<wxString>( "git.ssh_key",
193 &m_GitSSHKey, "" ) );
194
195 m_params.emplace_back( new PARAM<wxString>( "net_inspector_panel.filter_text",
197 m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.filter_by_net_name",
199 m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.filter_by_netclass",
201 m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.group_by_netclass",
203 m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.group_by_constraint",
205 m_params.emplace_back( new PARAM_LIST<wxString>( "net_inspector_panel.custom_group_rules",
207 {} ) );
208 m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.show_zero_pad_nets",
209 &m_NetInspectorPanel.show_zero_pad_nets, false ) );
210 m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.show_unconnected_nets",
211 &m_NetInspectorPanel.show_unconnected_nets, false ) );
212 m_params.emplace_back( new PARAM<int>( "net_inspector_panel.sorting_column",
213 &m_NetInspectorPanel.sorting_column, -1 ) );
214 m_params.emplace_back( new PARAM<bool>( "net_inspector_panel.sort_ascending",
215 &m_NetInspectorPanel.sort_order_asc, true ) );
216 m_params.emplace_back( new PARAM_LIST<int>( "net_inspector_panel.col_order",
217 &m_NetInspectorPanel.col_order, {} ) );
218 m_params.emplace_back( new PARAM_LIST<int>( "net_inspector_panel.col_widths",
219 &m_NetInspectorPanel.col_widths, {} ) );
220 m_params.emplace_back( new PARAM_LIST<bool>( "net_inspector_panel.col_hidden",
221 &m_NetInspectorPanel.col_hidden, {} ) );
222 m_params.emplace_back( new PARAM_LIST<wxString>( "net_inspector_panel.expanded_rows",
223 &m_NetInspectorPanel.expanded_rows, {} ) );
224
225 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "project.files",
226 [&]() -> nlohmann::json
227 {
228 nlohmann::json ret = nlohmann::json::array();
229
230 for( PROJECT_FILE_STATE& fileState : m_files )
231 {
232 nlohmann::json file;
233 file["name"] = fileState.fileName;
234 file["open"] = fileState.open;
235
236 nlohmann::json window;
237 window["maximized"] = fileState.window.maximized;
238 window["size_x"] = fileState.window.size_x;
239 window["size_y"] = fileState.window.size_y;
240 window["pos_x"] = fileState.window.pos_x;
241 window["pos_y"] = fileState.window.pos_y;
242 window["display"] = fileState.window.display;
243
244 file["window"] = window;
245
246 ret.push_back( file );
247 }
248
249 return ret;
250 },
251 [&]( const nlohmann::json& aVal )
252 {
253 if( !aVal.is_array() || aVal.empty() )
254 {
255 return;
256 }
257
258 m_files.clear();
259
260 for( const nlohmann::json& file : aVal )
261 {
262 PROJECT_FILE_STATE fileState;
263
264 try
265 {
266 SetIfPresent( file, "name", fileState.fileName );
267 SetIfPresent( file, "open", fileState.open );
268 SetIfPresent( file, "window.size_x", fileState.window.size_x );
269 SetIfPresent( file, "window.size_y", fileState.window.size_y );
270 SetIfPresent( file, "window.pos_x", fileState.window.pos_x );
271 SetIfPresent( file, "window.pos_y", fileState.window.pos_y );
272 SetIfPresent( file, "window.maximized", fileState.window.maximized );
273 SetIfPresent( file, "window.display", fileState.window.display );
274
275 m_files.push_back( fileState );
276 }
277 catch( ... )
278 {
279 // Non-integer or out of range entry in the array; ignore
280 }
281 }
282
283 },
284 {
285 } ) );
286
287 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "schematic.selection_filter",
288 [&]() -> nlohmann::json
289 {
290 nlohmann::json ret;
291
292 ret["lockedItems"] = m_SchSelectionFilter.lockedItems;
293 ret["symbols"] = m_SchSelectionFilter.symbols;
294 ret["text"] = m_SchSelectionFilter.text;
295 ret["wires"] = m_SchSelectionFilter.wires;
296 ret["labels"] = m_SchSelectionFilter.labels;
297 ret["pins"] = m_SchSelectionFilter.pins;
298 ret["graphics"] = m_SchSelectionFilter.graphics;
299 ret["images"] = m_SchSelectionFilter.images;
300 ret["otherItems"] = m_SchSelectionFilter.otherItems;
301
302 return ret;
303 },
304 [&]( const nlohmann::json& aVal )
305 {
306 if( aVal.empty() || !aVal.is_object() )
307 return;
308
309 SetIfPresent( aVal, "lockedItems", m_SchSelectionFilter.lockedItems );
310 SetIfPresent( aVal, "symbols", m_SchSelectionFilter.symbols );
311 SetIfPresent( aVal, "text", m_SchSelectionFilter.text );
312 SetIfPresent( aVal, "wires", m_SchSelectionFilter.wires );
313 SetIfPresent( aVal, "labels", m_SchSelectionFilter.labels );
314 SetIfPresent( aVal, "pins", m_SchSelectionFilter.pins );
315 SetIfPresent( aVal, "graphics", m_SchSelectionFilter.graphics );
316 SetIfPresent( aVal, "images", m_SchSelectionFilter.images );
317 SetIfPresent( aVal, "otherItems", m_SchSelectionFilter.otherItems );
318 },
319 {
320 { "lockedItems", false },
321 { "symbols", true },
322 { "text", true },
323 { "wires", true },
324 { "labels", true },
325 { "pins", true },
326 { "graphics", true },
327 { "images", true },
328 { "otherItems", true }
329 } ) );
330
331 registerMigration( 1, 2,
332 [&]()
333 {
339 std::string ptr( "board.visible_items" );
340
341 if( Contains( ptr ) )
342 {
343 if( At( ptr ).is_array() )
344 {
345 At( ptr ).push_back( LAYER_PADS - GAL_LAYER_ID_START );
346 At( ptr ).push_back( LAYER_ZONES - GAL_LAYER_ID_START );
347 }
348 else
349 {
350 At( "board" ).erase( "visible_items" );
351 }
352 }
353
354 return true;
355 } );
356
357 registerMigration( 2, 3,
358 [&]()
359 {
367 const std::map<int, int> offsets = {
368 { 22, 34 }, // LAYER_PAD_HOLEWALLS
369 { 23, 22 }, // LAYER_VIA_HOLES
370 { 24, 35 }, // LAYER_VIA_HOLEWALLS
371 { 25, 23 }, // LAYER_DRC_ERROR
372 { 26, 36 }, // LAYER_DRC_WARNING
373 { 27, 37 }, // LAYER_DRC_EXCLUSION
374 { 28, 38 }, // LAYER_MARKER_SHADOWS
375 { 29, 24 }, // LAYER_DRAWINGSHEET
376 { 30, 25 }, // LAYER_GP_OVERLAY
377 { 31, 26 }, // LAYER_SELECT_OVERLAY
378 { 32, 27 }, // LAYER_PCB_BACKGROUND
379 { 33, 28 }, // LAYER_CURSOR
380 { 34, 29 }, // LAYER_AUX_ITEM
381 { 35, 30 }, // LAYER_DRAW_BITMAPS
382 { 39, 32 }, // LAYER_PADS
383 { 40, 33 }, // LAYER_ZONES
384 };
385
386 std::string ptr( "board.visible_items" );
387
388 if( Contains( ptr ) && At( ptr ).is_array() )
389 {
390 nlohmann::json visible = nlohmann::json::array();
391
392 for( const nlohmann::json& val : At( ptr ) )
393 {
394 try
395 {
396 int layer = val.get<int>();
397
398 if( offsets.count( layer ) )
399 visible.push_back( offsets.at( layer ) );
400 else
401 visible.push_back( layer );
402 }
403 catch( ... )
404 {
405 // skip invalid value
406 }
407 }
408
409 At( "board" )["visible_items"] = visible;
410 }
411
412 return true;
413 } );
414
415 registerMigration( 3, 4,
416 [&]()
417 {
418 // Schema version 3 to 4: LAYER_SHAPES added to visibility controls
419
420 std::string ptr( "board.visible_items" );
421
422 if( Contains( ptr ) )
423 {
424 if( At( ptr ).is_array() )
425 At( ptr ).push_back( LAYER_SHAPES - GAL_LAYER_ID_START );
426 else
427 At( "board" ).erase( "visible_items" );
428 }
429
430 return true;
431 } );
432}
433
434
435bool PROJECT_LOCAL_SETTINGS::MigrateFromLegacy( wxConfigBase* aLegacyConfig )
436{
442 return true;
443}
444
445
446bool PROJECT_LOCAL_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce )
447{
448 wxASSERT( m_project );
449
451
452 return JSON_SETTINGS::SaveToFile( aDirectory, aForce );
453}
454
455
456bool PROJECT_LOCAL_SETTINGS::SaveAs( const wxString& aDirectory, const wxString& aFile )
457{
458 Set( "meta.filename", aFile + "." + FILEEXT::ProjectLocalSettingsFileExtension );
459 SetFilename( aFile );
460
461 return JSON_SETTINGS::SaveToFile( aDirectory, true );
462}
463
464
466{
467 auto it = std::find_if( m_files.begin(), m_files.end(),
468 [&aFileName]( const PROJECT_FILE_STATE &a )
469 {
470 return a.fileName == aFileName;
471 } );
472
473 if( it != m_files.end() )
474 {
475 return &( *it );
476 }
477
478 return nullptr;
479}
480
481
482void PROJECT_LOCAL_SETTINGS::SaveFileState( const wxString& aFileName,
483 const WINDOW_SETTINGS* aWindowCfg, bool aOpen )
484{
485 auto it = std::find_if( m_files.begin(), m_files.end(),
486 [&aFileName]( const PROJECT_FILE_STATE& a )
487 {
488 return a.fileName == aFileName;
489 } );
490
491 if( it == m_files.end() )
492 {
493 PROJECT_FILE_STATE fileState;
494 fileState.fileName = aFileName;
495 fileState.open = false;
496 fileState.window.maximized = false;
497 fileState.window.size_x = -1;
498 fileState.window.size_y = -1;
499 fileState.window.pos_x = -1;
500 fileState.window.pos_y = -1;
501 fileState.window.display = 0;
502
503 m_files.push_back( fileState );
504
505 it = m_files.end() - 1;
506 }
507
508 ( *it ).window = aWindowCfg->state;
509 ( *it ).open = aOpen;
510}
511
512
514{
515 m_files.clear();
516}
@ NORMAL
Use all material properties from model file.
HIGH_CONTRAST_MODE
Determine how inactive layers should be displayed.
@ RATSNEST
Net/netclass colors are shown on ratsnest lines only.
GAL_SET & set()
Definition: layer_ids.h:324
static GAL_SET DefaultVisible()
Definition: lset.cpp:903
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...
static bool SetIfPresent(const nlohmann::json &aObj, const std::string &aPath, wxString &aTarget)
Sets the given string if the given key/path is present.
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
bool m_deleteLegacyAfterMigration
Whether or not to delete legacy file after migration.
void SetFilename(const wxString &aFilename)
Definition: json_settings.h:84
virtual bool SaveToFile(const wxString &aDirectory="", bool aForce=false)
Calls Store() and then writes the contents of the JSON document to a file.
int ParseHex(const char *aStart, int aCount)
Convert the output of FmtHex() and replaces this set's values with those given in the input string.
Definition: lset.cpp:340
static LSET AllLayersMask()
Definition: lset.cpp:767
std::string FmtHex() const
Return a hex string showing contents of this LSEQ.
Definition: lset.cpp:302
Stores an enum as an integer.
Definition: parameters.h:226
Like a normal param, but with custom getter and setter functions.
Definition: parameters.h:293
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
LSET m_VisibleLayers
Board settings.
double m_PadOpacity
Opacity override for SMD pads and PTH.
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
Calls Store() and then writes the contents of the JSON document to a file.
std::vector< PROJECT_FILE_STATE > m_files
Project scope.
double m_ViaOpacity
Opacity override for all types of via.
PANEL_NET_INSPECTOR_SETTINGS m_NetInspectorPanel
The state of the net inspector panel.
PCB_SELECTION_FILTER_OPTIONS m_PcbSelectionFilter
State of the selection filter widgets.
wxString m_ActiveLayerPreset
The name of a LAYER_PRESET that is currently activated (or blank if none)
double m_TrackOpacity
Opacity override for all tracks.
PROJECT * m_project
A link to the owning project.
double m_ZoneOpacity
Opacity override for filled zones.
bool m_AutoTrackWidth
The current setting for whether to automatically adjust track widths to match.
ZONE_DISPLAY_MODE m_ZoneDisplayMode
How zones are drawn.
double m_ShapeOpacity
Opacity override for graphic shapes.
PCB_LAYER_ID m_ActiveLayer
The current (active) board layer for editing.
HIGH_CONTRAST_MODE m_ContrastModeDisplay
The current contrast mode.
NET_COLOR_MODE m_NetColorMode
The current net color mode.
bool MigrateFromLegacy(wxConfigBase *aLegacyConfig) override
Migrates from wxConfig to JSON-based configuration.
GAL_SET m_VisibleItems
The GAL layers (aka items) that are turned on for viewing (.
std::vector< wxString > m_HiddenNets
A list of netnames that have been manually hidden in the board editor.
PROJECT_LOCAL_SETTINGS(PROJECT *aProject, const wxString &aFilename)
std::set< wxString > m_HiddenNetclasses
void SaveFileState(const wxString &aFileName, const WINDOW_SETTINGS *aWindowCfg, bool aOpen)
double m_ImageOpacity
Opacity override for user images.
const PROJECT_FILE_STATE * GetFileState(const wxString &aFileName)
Container for project specific data.
Definition: project.h:62
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:147
static const std::string ProjectLocalSettingsFileExtension
SETTINGS_LOC
Definition: json_settings.h:54
constexpr PCB_LAYER_ID PCBNEW_LAYER_ID_START
Definition: layer_ids.h:140
@ GAL_LAYER_ID_START
Definition: layer_ids.h:195
@ LAYER_ZONES
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:235
@ LAYER_SHAPES
Copper graphic shape opacity/visibility (color ignored)
Definition: layer_ids.h:246
@ LAYER_PADS
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:234
@ F_Fab
Definition: layer_ids.h:120
@ UNDEFINED_LAYER
Definition: layer_ids.h:61
@ F_Cu
Definition: layer_ids.h:64
const int projectLocalSettingsVersion
std::vector< wxString > custom_group_rules
bool otherItems
Anything not fitting one of the above categories.
bool graphics
Graphic lines, shapes, polygons.
bool footprints
Allow selecting entire footprints.
bool text
Text (free or attached to a footprint)
bool lockedItems
Allow selecting locked items.
struct WINDOW_STATE window
Stores the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:74
WINDOW_STATE state
Definition: app_settings.h:75
unsigned int display
Definition: app_settings.h:67