KiCad PCB EDA Suite
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 <project.h>
25 #include <settings/parameters.h>
26 
28 
29 
30 PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxString& aFilename ) :
32  /* aCreateIfMissing = */ true, /* aCreateIfDefault = */ false,
33  /* aWriteFile = */ true ),
34  m_ActiveLayer( UNDEFINED_LAYER ),
35  m_ContrastModeDisplay( HIGH_CONTRAST_MODE::NORMAL ),
36  m_NetColorMode( NET_COLOR_MODE::RATSNEST ),
37  m_RatsnestMode( RATSNEST_MODE::ALL ),
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_SelectionFilter(),
45  m_project( aProject )
46 {
47  // Keep old files around
49 
50  m_params.emplace_back( new PARAM_LAMBDA<std::string>( "board.visible_layers",
51  [&]() -> std::string
52  {
53  return m_VisibleLayers.FmtHex();
54  },
55  [&]( const std::string& aString )
56  {
57  m_VisibleLayers.ParseHex( aString.c_str(), aString.size() );
58  },
60 
61  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "board.visible_items",
62  [&]() -> nlohmann::json
63  {
64  nlohmann::json ret = nlohmann::json::array();
65 
66  for( size_t i = 0; i < m_VisibleItems.size(); i++ )
67  if( m_VisibleItems.test( i ) )
68  ret.push_back( i );
69 
70  return ret;
71  },
72  [&]( const nlohmann::json& aVal )
73  {
74  if( !aVal.is_array() || aVal.empty() )
75  {
77  return;
78  }
79 
80  m_VisibleItems.reset();
81 
82  for( const nlohmann::json& entry : aVal )
83  {
84  try
85  {
86  int i = entry.get<int>();
87  m_VisibleItems.set( i );
88  }
89  catch( ... )
90  {
91  // Non-integer or out of range entry in the array; ignore
92  }
93  }
94  },
95  {} ) );
96 
97  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "board.selection_filter",
98  [&]() -> nlohmann::json
99  {
100  nlohmann::json ret;
101 
102  ret["lockedItems"] = m_SelectionFilter.lockedItems;
103  ret["footprints"] = m_SelectionFilter.footprints;
104  ret["text"] = m_SelectionFilter.text;
105  ret["tracks"] = m_SelectionFilter.tracks;
106  ret["vias"] = m_SelectionFilter.vias;
107  ret["pads"] = m_SelectionFilter.pads;
108  ret["graphics"] = m_SelectionFilter.graphics;
109  ret["zones"] = m_SelectionFilter.zones;
110  ret["keepouts"] = m_SelectionFilter.keepouts;
111  ret["dimensions"] = m_SelectionFilter.dimensions;
112  ret["otherItems"] = m_SelectionFilter.otherItems;
113 
114  return ret;
115  },
116  [&]( const nlohmann::json& aVal )
117  {
118  if( aVal.empty() || !aVal.is_object() )
119  return;
120 
121  SetIfPresent( aVal, "lockedItems", m_SelectionFilter.lockedItems );
122  SetIfPresent( aVal, "footprints", m_SelectionFilter.footprints );
123  SetIfPresent( aVal, "text", m_SelectionFilter.text );
124  SetIfPresent( aVal, "tracks", m_SelectionFilter.tracks );
125  SetIfPresent( aVal, "vias", m_SelectionFilter.vias );
126  SetIfPresent( aVal, "pads", m_SelectionFilter.pads );
127  SetIfPresent( aVal, "graphics", m_SelectionFilter.graphics );
128  SetIfPresent( aVal, "zones", m_SelectionFilter.zones );
129  SetIfPresent( aVal, "keepouts", m_SelectionFilter.keepouts );
130  SetIfPresent( aVal, "dimensions", m_SelectionFilter.dimensions );
131  SetIfPresent( aVal, "otherItems", m_SelectionFilter.otherItems );
132  },
133  {
134  { "lockedItems", true },
135  { "footprints", true },
136  { "text", true },
137  { "tracks", true },
138  { "vias", true },
139  { "pads", true },
140  { "graphics", true },
141  { "zones", true },
142  { "keepouts", true },
143  { "dimensions", true },
144  { "otherItems", true }
145  } ) );
146 
147  m_params.emplace_back( new PARAM_ENUM<PCB_LAYER_ID>( "board.active_layer",
149 
150  m_params.emplace_back( new PARAM<wxString>( "board.active_layer_preset",
151  &m_ActiveLayerPreset, "" ) );
152 
153  m_params.emplace_back( new PARAM_ENUM<HIGH_CONTRAST_MODE>( "board.high_contrast_mode",
156 
157  m_params.emplace_back( new PARAM<double>( "board.opacity.tracks", &m_TrackOpacity, 1.0 ) );
158  m_params.emplace_back( new PARAM<double>( "board.opacity.vias", &m_ViaOpacity, 1.0 ) );
159  m_params.emplace_back( new PARAM<double>( "board.opacity.pads", &m_PadOpacity, 1.0 ) );
160  m_params.emplace_back( new PARAM<double>( "board.opacity.zones", &m_ZoneOpacity, 0.6 ) );
161 
162  m_params.emplace_back( new PARAM_LIST<wxString>( "board.hidden_nets", &m_HiddenNets, {} ) );
163 
164  m_params.emplace_back( new PARAM_ENUM<NET_COLOR_MODE>( "board.net_color_mode",
167 
168  m_params.emplace_back( new PARAM_ENUM<RATSNEST_MODE>( "board.ratsnest_display_mode",
171 
172  m_params.emplace_back( new PARAM<bool>( "board.auto_track_width",
173  &m_AutoTrackWidth, true ) );
174 
175  m_params.emplace_back( new PARAM_ENUM<ZONE_DISPLAY_MODE>( "board.zone_display_mode",
179 
180  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "project.files",
181  [&]() -> nlohmann::json
182  {
183  nlohmann::json ret = nlohmann::json::array();
184 
185  for( PROJECT_FILE_STATE& fileState : m_files )
186  {
187  nlohmann::json file;
188  file["name"] = fileState.fileName;
189  file["open"] = fileState.open;
190 
191  nlohmann::json window;
192  window["maximized"] = fileState.window.maximized;
193  window["size_x"] = fileState.window.size_x;
194  window["size_y"] = fileState.window.size_y;
195  window["pos_x"] = fileState.window.pos_x;
196  window["pos_y"] = fileState.window.pos_y;
197  window["display"] = fileState.window.display;
198 
199  file["window"] = window;
200 
201  ret.push_back( file );
202  }
203 
204  return ret;
205  },
206  [&]( const nlohmann::json& aVal )
207  {
208  if( !aVal.is_array() || aVal.empty() )
209  {
210  return;
211  }
212 
213  for( const nlohmann::json& file : aVal )
214  {
215  PROJECT_FILE_STATE fileState;
216 
217  try
218  {
219  SetIfPresent( file, "name", fileState.fileName );
220  SetIfPresent( file, "open", fileState.open );
221  SetIfPresent( file, "window.size_x", fileState.window.size_x );
222  SetIfPresent( file, "window.size_y", fileState.window.size_y );
223  SetIfPresent( file, "window.pos_x", fileState.window.pos_x );
224  SetIfPresent( file, "window.pos_y", fileState.window.pos_y );
225  SetIfPresent( file, "window.maximized", fileState.window.maximized );
226  SetIfPresent( file, "window.display", fileState.window.display );
227 
228  m_files.push_back( fileState );
229  }
230  catch( ... )
231  {
232  // Non-integer or out of range entry in the array; ignore
233  }
234  }
235 
236  },
237  {
238  } ) );
239 
240  registerMigration( 1, 2,
241  [&]()
242  {
248  std::string ptr( "board.visible_items" );
249 
250  if( Contains( ptr ) )
251  {
252  if( At( ptr ).is_array() )
253  {
254  At( ptr ).push_back( LAYER_PADS );
255  At( ptr ).push_back( LAYER_ZONES );
256  }
257  else
258  {
259  At( "board" ).erase( "visible_items" );
260  }
261  }
262 
263  return true;
264  } );
265 
266  registerMigration( 2, 3,
267  [&]()
268  {
275  const std::map<int, int> offsets = {
277  { 22, 34 }, // LAYER_PAD_HOLEWALLS
278  { 23, 22 }, // LAYER_VIA_HOLES
279  { 24, 35 }, // LAYER_VIA_HOLEWALLS
280  { 25, 23 }, // LAYER_DRC_ERROR
281  { 26, 36 }, // LAYER_DRC_WARNING
282  { 27, 37 }, // LAYER_DRC_EXCLUSION
283  { 28, 38 }, // LAYER_MARKER_SHADOWS
284  { 29, 24 }, // LAYER_DRAWINGSHEET
285  { 30, 25 }, // LAYER_GP_OVERLAY
286  { 31, 26 }, // LAYER_SELECT_OVERLAY
287  { 32, 27 }, // LAYER_PCB_BACKGROUND
288  { 33, 28 }, // LAYER_CURSOR
289  { 34, 29 }, // LAYER_AUX_ITEM
290  { 35, 30 }, // LAYER_DRAW_BITMAPS
291  { 39, 32 }, // LAYER_PADS
292  { 40, 33 }, // LAYER_ZONES
293  };
294 
295  std::string ptr( "board.visible_items" );
296 
297  if( Contains( ptr ) && At( ptr ).is_array() )
298  {
299  nlohmann::json visible = nlohmann::json::array();
300 
301  for( const nlohmann::json& val : At( ptr ) )
302  {
303  try
304  {
305  int layer = val.get<int>();
306 
307  if( offsets.count( layer ) )
308  visible.push_back( offsets.at( layer ) );
309  else
310  visible.push_back( layer );
311  }
312  catch( ... )
313  {
314  // skip invalid value
315  }
316  }
317 
318  At( "board" )["visible_items"] = visible;
319  }
320 
321  return true;
322  } );
323 }
324 
325 
326 bool PROJECT_LOCAL_SETTINGS::MigrateFromLegacy( wxConfigBase* aLegacyConfig )
327 {
333  return true;
334 }
335 
336 
337 bool PROJECT_LOCAL_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce )
338 {
339  wxASSERT( m_project );
340 
341  Set( "meta.filename", m_project->GetProjectName() + "." + ProjectLocalSettingsFileExtension );
342 
343  return JSON_SETTINGS::SaveToFile( aDirectory, aForce );
344 }
345 
346 
347 bool PROJECT_LOCAL_SETTINGS::SaveAs( const wxString& aDirectory, const wxString& aFile )
348 {
349  Set( "meta.filename", aFile + "." + ProjectLocalSettingsFileExtension );
350  SetFilename( aFile );
351 
352  return JSON_SETTINGS::SaveToFile( aDirectory, true );
353 }
354 
355 
356 const PROJECT_FILE_STATE* PROJECT_LOCAL_SETTINGS::GetFileState( const wxString& aFileName )
357 {
358  auto it = std::find_if( m_files.begin(), m_files.end(),
359  [&aFileName]( const PROJECT_FILE_STATE &a )
360  {
361  return a.fileName == aFileName;
362  } );
363 
364  if( it != m_files.end() )
365  {
366  return &( *it );
367  }
368 
369  return nullptr;
370 }
371 
372 
373 void PROJECT_LOCAL_SETTINGS::SaveFileState( const wxString& aFileName,
374  const WINDOW_SETTINGS* aWindowCfg, bool aOpen )
375 {
376  auto it = std::find_if( m_files.begin(), m_files.end(),
377  [&aFileName]( const PROJECT_FILE_STATE& a )
378  {
379  return a.fileName == aFileName;
380  } );
381 
382  if( it == m_files.end() )
383  {
384  PROJECT_FILE_STATE fileState;
385  fileState.fileName = aFileName;
386  fileState.open = false;
387  fileState.window.maximized = false;
388  fileState.window.size_x = -1;
389  fileState.window.size_y = -1;
390  fileState.window.pos_x = -1;
391  fileState.window.pos_y = -1;
392  fileState.window.display = 0;
393 
394  m_files.push_back( fileState );
395 
396  it = m_files.end() - 1;
397  }
398 
399  ( *it ).window = aWindowCfg->state;
400  ( *it ).open = aOpen;
401 }
402 
403 
405 {
406  m_files.clear();
407 }
LSET m_VisibleLayers
Board settings.
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...
bool otherItems
Anything not fitting one of the above categories.
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
void SaveFileState(const wxString &aFileName, const WINDOW_SETTINGS *aWindowCfg, bool aOpen)
Container for project specific data.
Definition: project.h:62
const int projectLocalSettingsVersion
Like a normal param, but with custom getter and setter functions.
Definition: parameters.h:280
Ratsnest lines are drawn to items on visible layers only.
double m_TrackOpacity
Opacity override for all tracks.
Meta control for all pads opacity/visibility (color ignored)
Definition: layer_ids.h:237
ZONE_DISPLAY_MODE m_ZoneDisplayMode
How zones are drawn.
bool MigrateFromLegacy(wxConfigBase *aLegacyConfig) override
Migrates from wxConfig to JSON-based configuration.
Net/netclass colors are shown on all net copper.
Net/netclass colors are shown on ratsnest lines only.
SETTINGS_LOC
Definition: json_settings.h:46
double m_ViaOpacity
Opacity override for all types of via.
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
Stores an enum as an integer.
Definition: parameters.h:215
NET_COLOR_MODE m_NetColorMode
The current net color mode.
PCB_LAYER_ID m_ActiveLayer
The current (active) board layer for editing.
All except INITIAL_ADD.
Definition: view_item.h:53
nlohmann::json json
Definition: gerbview.cpp:41
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...
Control for copper zone opacity/visibility (color ignored)
Definition: layer_ids.h:238
Ratsnest lines are drawn to items on all layers (default)
bool m_deleteLegacyAfterMigration
Whether or not to delete legacy file after migration.
const std::string ProjectLocalSettingsFileExtension
double m_PadOpacity
Opacity override for SMD pads and PTH.
Stores the common settings that are saved and loaded for each window / frame.
Definition: app_settings.h:81
virtual bool SaveToFile(const wxString &aDirectory="", bool aForce=false)
bool text
Text (free or attached to a footprint)
GAL_SET m_VisibleItems
The GAL layers (aka items) that are turned on for viewing (.
wxString m_ActiveLayerPreset
The name of a LAYER_PRESET that is currently activated (or blank if none)
bool dimensions
Dimension items.
bool graphics
Graphic lines, shapes, polygons.
Use all material properties from model file.
static bool SetIfPresent(const nlohmann::json &aObj, const std::string &aPath, wxString &aTarget)
Sets the given string if the given key/path is present.
struct WINDOW_STATE window
PROJECT * m_project
A link to the owning project.
Inactive layers are shown normally (no high-contrast mode)
HIGH_CONTRAST_MODE
Determine how inactive layers should be displayed.
static GAL_SET DefaultVisible()
Definition: lset.cpp:942
RATSNEST_MODE m_RatsnestMode
The current ratsnest draw mode.
static LSET AllLayersMask()
Definition: lset.cpp:796
bool m_AutoTrackWidth
The current setting for whether to automatically adjust track widths to match.
double m_ZoneOpacity
Opacity override for filled zones.
bool footprints
Allow selecting entire footprints.
const PROJECT_FILE_STATE * GetFileState(const wxString &aFileName)
bool lockedItems
Allow selecting locked items.
HIGH_CONTRAST_MODE m_ContrastModeDisplay
The current contrast mode.
void registerMigration(int aOldSchemaVersion, int aNewSchemaVersion, std::function< bool(void)> aMigrator)
Registers a migration from one schema version to another.
Net (and netclass) colors are not shown.
WINDOW_STATE state
Definition: app_settings.h:83
Definition: layer_ids.h:71
std::string FmtHex() const
Return a hex string showing contents of this LSEQ.
Definition: lset.cpp:321
std::vector< wxString > m_HiddenNets
A list of netnames that have been manually hidden in the board editor.
SELECTION_FILTER_OPTIONS m_SelectionFilter
State of the selection filter widget.
GAL_SET & set()
Definition: layer_ids.h:306
virtual const wxString GetProjectName() const
Return the short name of the project.
Definition: project.cpp:128
bool SaveAs(const wxString &aDirectory, const wxString &aFile)
bool Contains(const std::string &aPath) const
PROJECT_LOCAL_SETTINGS(PROJECT *aProject, const wxString &aFilename)
Inactive layers are hidden.
void SetFilename(const wxString &aFilename)
Definition: json_settings.h:76
unsigned int display
Definition: app_settings.h:75
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:359
std::vector< PROJECT_FILE_STATE > m_files
Project scope.