KiCad PCB EDA Suite
project_file.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  * @author Jon Evans <jon@craftyjon.com>
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 <config_params.h>
22 #include <project.h>
23 #include <project/net_settings.h>
24 #include <project/project_file.h>
26 #include <settings/parameters.h>
28 #include <wx/config.h>
29 #include <wx/log.h>
30 
31 extern const char* traceSettings;
32 
35 
36 
37 PROJECT_FILE::PROJECT_FILE( const wxString& aFullPath ) :
39  m_sheets(),
40  m_boards(),
41  m_project( nullptr ),
42  m_ErcSettings( nullptr ),
43  m_SchematicSettings( nullptr ),
44  m_TemplateFieldNames( nullptr ),
45  m_BoardSettings()
46 {
47  // Keep old files around
49 
50  m_params.emplace_back( new PARAM_LIST<FILE_INFO_PAIR>( "sheets", &m_sheets, {} ) );
51 
52  m_params.emplace_back( new PARAM_LIST<FILE_INFO_PAIR>( "boards", &m_boards, {} ) );
53 
54  m_params.emplace_back( new PARAM_WXSTRING_MAP( "text_variables", &m_TextVars, {} ) );
55 
56  m_params.emplace_back(
57  new PARAM_LIST<wxString>( "libraries.pinned_symbol_libs", &m_PinnedSymbolLibs, {} ) );
58 
59  m_params.emplace_back( new PARAM_LIST<wxString>(
60  "libraries.pinned_footprint_libs", &m_PinnedFootprintLibs, {} ) );
61 
62  m_params.emplace_back(
63  new PARAM_PATH_LIST( "cvpcb.equivalence_files", &m_EquivalenceFiles, {} ) );
64 
65  m_params.emplace_back(
66  new PARAM_PATH( "pcbnew.page_layout_descr_file", &m_BoardPageLayoutDescrFile, "" ) );
67 
68  m_params.emplace_back(
69  new PARAM_PATH( "pcbnew.last_paths.netlist", &m_PcbLastPath[LAST_PATH_NETLIST], "" ) );
70 
71  m_params.emplace_back(
72  new PARAM_PATH( "pcbnew.last_paths.step", &m_PcbLastPath[LAST_PATH_STEP], "" ) );
73 
74  m_params.emplace_back(
75  new PARAM_PATH( "pcbnew.last_paths.idf", &m_PcbLastPath[LAST_PATH_IDF], "" ) );
76 
77  m_params.emplace_back(
78  new PARAM_PATH( "pcbnew.last_paths.vmrl", &m_PcbLastPath[LAST_PATH_VRML], "" ) );
79 
80  m_params.emplace_back( new PARAM_PATH(
81  "pcbnew.last_paths.specctra_dsn", &m_PcbLastPath[LAST_PATH_SPECCTRADSN], "" ) );
82 
83  m_params.emplace_back(
84  new PARAM_PATH( "pcbnew.last_paths.gencad", &m_PcbLastPath[LAST_PATH_GENCAD], "" ) );
85 
86  m_params.emplace_back( new PARAM<wxString>( "schematic.legacy_lib_dir", &m_LegacyLibDir, "" ) );
87 
88  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "schematic.legacy_lib_list",
89  [&]() -> nlohmann::json
90  {
91  nlohmann::json ret = nlohmann::json::array();
92 
93  for( const wxString& libName : m_LegacyLibNames )
94  ret.push_back( libName );
95 
96  return ret;
97  },
98  [&]( const nlohmann::json& aJson )
99  {
100  if( aJson.empty() || !aJson.is_array() )
101  return;
102 
103  m_LegacyLibNames.clear();
104 
105  for( const nlohmann::json& entry : aJson )
106  m_LegacyLibNames.push_back( entry.get<wxString>() );
107  }, {} ) );
108 
109  m_NetSettings = std::make_shared<NET_SETTINGS>( this, "net_settings" );
110 
111  m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "board.layer_presets",
112  [&]() -> nlohmann::json
113  {
114  nlohmann::json ret = nlohmann::json::array();
115 
116  for( const LAYER_PRESET& preset : m_LayerPresets )
117  {
118  nlohmann::json js = {
119  { "name", preset.name },
120  { "activeLayer", preset.activeLayer }
121  };
122 
123  nlohmann::json layers = nlohmann::json::array();
124 
125  for( PCB_LAYER_ID layer : preset.layers.Seq() )
126  layers.push_back( static_cast<int>( layer ) );
127 
128  js["layers"] = layers;
129 
130  nlohmann::json renderLayers = nlohmann::json::array();
131 
132  for( GAL_LAYER_ID layer : preset.renderLayers.Seq() )
133  renderLayers.push_back( static_cast<int>( layer ) );
134 
135  js["renderLayers"] = renderLayers;
136 
137  ret.push_back( js );
138  }
139 
140  return ret;
141  },
142  [&]( const nlohmann::json& aVal )
143  {
144  if( aVal.empty() || !aVal.is_array() )
145  return;
146 
147  m_LayerPresets.clear();
148 
149  for( const nlohmann::json& preset : aVal )
150  {
151  if( preset.contains( "name" ) )
152  {
153  LAYER_PRESET p( preset.at( "name" ).get<wxString>() );
154 
155  if( preset.contains( "activeLayer" ) &&
156  preset.at( "activeLayer" ).is_number_integer() )
157  {
158  int active = preset.at( "activeLayer" ).get<int>();
159 
160  if( active >= 0 && active < PCB_LAYER_ID_COUNT )
161  p.activeLayer = static_cast<PCB_LAYER_ID>( active );
162  }
163 
164  if( preset.contains( "layers" ) && preset.at( "layers" ).is_array() )
165  {
166  for( const nlohmann::json& layer : preset.at( "layers" ) )
167  {
168  if( layer.is_number_integer() )
169  {
170  int layerNum = layer.get<int>();
171 
172  if( layerNum >= 0 && layerNum < PCB_LAYER_ID_COUNT )
173  p.layers.set( layerNum );
174  }
175  }
176  }
177 
178  if( preset.contains( "renderLayers" )
179  && preset.at( "renderLayers" ).is_array() )
180  {
181  for( const nlohmann::json& layer : preset.at( "renderLayers" ) )
182  {
183  if( layer.is_number_integer() )
184  {
185  int layerNum = layer.get<int>();
186 
187  if( layerNum >= GAL_LAYER_ID_START
188  && layerNum < GAL_LAYER_ID_END )
189  p.layers.set( layerNum );
190  }
191  }
192  }
193 
194  m_LayerPresets.emplace_back( p );
195  }
196  }
197  },
198  {} ) );
199 }
200 
201 
202 bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
203 {
204  bool ret = true;
205  wxString str;
206  long index = 0;
207 
208  std::set<wxString> group_blacklist;
209 
210  // Legacy files don't store board info; they assume board matches project name
211  // We will leave m_boards empty here so it can be populated with other code
212 
213  // First handle migration of data that will be stored locally in this object
214 
215  auto loadPinnedLibs =
216  [&]( const std::string& aDest )
217  {
218  int libIndex = 1;
219  wxString libKey = wxT( "PinnedItems" );
220  libKey << libIndex;
221 
222  nlohmann::json libs = nlohmann::json::array();
223 
224  while( aCfg->Read( libKey, &str ) )
225  {
226  libs.push_back( str );
227 
228  aCfg->DeleteEntry( libKey, true );
229 
230  libKey = wxT( "PinnedItems" );
231  libKey << ++libIndex;
232  }
233 
234  ( *this )[PointerFromString( aDest )] = libs;
235  };
236 
237  aCfg->SetPath( wxT( "/LibeditFrame" ) );
238  loadPinnedLibs( "libraries.pinned_symbol_libs" );
239 
240  aCfg->SetPath( wxT( "/ModEditFrame" ) );
241  loadPinnedLibs( "libraries.pinned_footprint_libs" );
242 
243  aCfg->SetPath( wxT( "/cvpcb/equfiles" ) );
244 
245  {
246  int eqIdx = 1;
247  wxString eqKey = wxT( "EquName" );
248  eqKey << eqIdx;
249 
250  nlohmann::json eqs = nlohmann::json::array();
251 
252  while( aCfg->Read( eqKey, &str ) )
253  {
254  eqs.push_back( str );
255 
256  eqKey = wxT( "EquName" );
257  eqKey << ++eqIdx;
258  }
259 
260  ( *this )[PointerFromString( "cvpcb.equivalence_files" )] = eqs;
261  }
262 
263  // All CvPcb params that we want to keep have been migrated above
264  group_blacklist.insert( wxT( "/cvpcb" ) );
265 
266  aCfg->SetPath( wxT( "/eeschema" ) );
267  fromLegacyString( aCfg, "LibDir", "schematic.legacy_lib_dir" );
268 
269  aCfg->SetPath( wxT( "/eeschema/libraries" ) );
270 
271  {
272  int libIdx = 1;
273  wxString libKey = wxT( "LibName" );
274  libKey << libIdx;
275 
276  nlohmann::json libs = nlohmann::json::array();
277 
278  while( aCfg->Read( libKey, &str ) )
279  {
280  libs.push_back( str );
281 
282  libKey = wxT( "LibName" );
283  libKey << ++libIdx;
284  }
285 
286  ( *this )[PointerFromString( "schematic.legacy_lib_list" )] = libs;
287  }
288 
289  group_blacklist.insert( wxT( "/eeschema" ) );
290 
291  aCfg->SetPath( wxT( "/text_variables" ) );
292 
293  {
294  int txtIdx = 1;
295  wxString txtKey;
296  txtKey << txtIdx;
297 
299 
300  while( aCfg->Read( txtKey, &str ) )
301  {
302  wxArrayString tokens = wxSplit( str, ':' );
303 
304  if( tokens.size() == 2 )
305  vars[ tokens[0].ToStdString() ] = tokens[1];
306 
307  txtKey.clear();
308  txtKey << ++txtIdx;
309  }
310 
311  ( *this )[PointerFromString( "text_variables" )] = vars;
312  }
313 
314  group_blacklist.insert( wxT( "/text_variables" ) );
315 
316  aCfg->SetPath( wxT( "/schematic_editor" ) );
317 
318  fromLegacyString( aCfg, "PageLayoutDescrFile", "schematic.page_layout_descr_file" );
319  fromLegacyString( aCfg, "PlotDirectoryName", "schematic.plot_directory" );
320  fromLegacyString( aCfg, "NetFmtName", "schematic.net_format_name" );
321  fromLegacy<bool>( aCfg, "SpiceAjustPassiveValues", "schematic.spice_adjust_passive_values" );
322  fromLegacy<int>( aCfg, "SubpartIdSeparator", "schematic.subpart_id_separator" );
323  fromLegacy<int>( aCfg, "SubpartFirstId", "schematic.subpart_first_id" );
324 
325  fromLegacy<int>( aCfg, "LineThickness", "schematic.drawing.default_line_thickness" );
326  fromLegacy<int>( aCfg, "WireThickness", "schematic.drawing.default_wire_thickness" );
327  fromLegacy<int>( aCfg, "BusThickness", "schematic.drawing.default_bus_thickness" );
328  fromLegacy<int>( aCfg, "LabSize", "schematic.drawing.default_text_size" );
329  fromLegacy<int>( aCfg, "PinSymbolSize", "schematic.drawing.pin_symbol_size" );
330  fromLegacy<int>( aCfg, "JunctionSize", "schematic.drawing.default_junction_size" );
331 
332  fromLegacyString( aCfg, "FieldNameTemplates", "schematic.drawing.field_names" );
333  fromLegacy<double>( aCfg, "TextOffsetRatio", "schematic.drawing.text_offset_ratio" );
334 
335  // All schematic_editor keys we keep are migrated above
336  group_blacklist.insert( wxT( "/schematic_editor" ) );
337 
338  aCfg->SetPath( wxT( "/pcbnew" ) );
339 
340  fromLegacyString( aCfg, "PageLayoutDescrFile", "pcbnew.page_layout_descr_file" );
341  fromLegacyString( aCfg, "LastNetListRead", "pcbnew.last_paths.netlist" );
342  fromLegacyString( aCfg, "LastSTEPExportPath", "pcbnew.last_paths.step" );
343  fromLegacyString( aCfg, "LastIDFExportPath", "pcbnew.last_paths.idf" );
344  fromLegacyString( aCfg, "LastVRMLExportPath", "pcbnew.last_paths.vmrl" );
345  fromLegacyString( aCfg, "LastSpecctraDSNExportPath", "pcbnew.last_paths.specctra_dsn" );
346  fromLegacyString( aCfg, "LastGenCADExportPath", "pcbnew.last_paths.gencad" );
347 
348  std::string bp = "board.design_settings.";
349 
350  {
351  int idx = 1;
352  wxString key = wxT( "DRCExclusion" );
353  key << idx;
354 
355  nlohmann::json exclusions = nlohmann::json::array();
356 
357  while( aCfg->Read( key, &str ) )
358  {
359  exclusions.push_back( str );
360 
361  key = wxT( "DRCExclusion" );
362  key << ++idx;
363  }
364 
365  ( *this )[PointerFromString( bp + "drc_exclusions" )] = exclusions;
366  }
367 
368  fromLegacy<bool>( aCfg, "AllowMicroVias", bp + "rules.allow_microvias" );
369  fromLegacy<bool>( aCfg, "AllowBlindVias", bp + "rules.allow_blind_buried_vias" );
370  fromLegacy<double>( aCfg, "MinClearance", bp + "rules.min_clearance" );
371  fromLegacy<double>( aCfg, "MinTrackWidth", bp + "rules.min_track_width" );
372  fromLegacy<double>( aCfg, "MinViaAnnulus", bp + "rules.min_via_annulus" );
373  fromLegacy<double>( aCfg, "MinViaDiameter", bp + "rules.min_via_diameter" );
374 
375  if( !fromLegacy<double>( aCfg, "MinThroughDrill", bp + "rules.min_through_hole_diameter" ) )
376  fromLegacy<double>( aCfg, "MinViaDrill", bp + "rules.min_through_hole_diameter" );
377 
378  fromLegacy<double>( aCfg, "MinMicroViaDiameter", bp + "rules.min_microvia_diameter" );
379  fromLegacy<double>( aCfg, "MinMicroViaDrill", bp + "rules.min_microvia_drill" );
380  fromLegacy<double>( aCfg, "MinHoleToHole", bp + "rules.min_hole_to_hole" );
381  fromLegacy<double>( aCfg, "CopperEdgeClearance", bp + "rules.min_copper_edge_clearance" );
382  fromLegacy<double>( aCfg, "SolderMaskClearance", bp + "rules.solder_mask_clearance" );
383  fromLegacy<double>( aCfg, "SolderMaskMinWidth", bp + "rules.solder_mask_min_width" );
384  fromLegacy<double>( aCfg, "SolderPasteClearance", bp + "rules.solder_paste_clearance" );
385  fromLegacy<double>( aCfg, "SolderPasteRatio", bp + "rules.solder_paste_margin_ratio" );
386 
387  if( !fromLegacy<double>( aCfg, "SilkLineWidth", bp + "defaults.silk_line_width" ) )
388  fromLegacy<double>( aCfg, "ModuleOutlineThickness", bp + "defaults.silk_line_width" );
389 
390  if( !fromLegacy<double>( aCfg, "SilkTextSizeV", bp + "defaults.silk_text_size_v" ) )
391  fromLegacy<double>( aCfg, "ModuleTextSizeV", bp + "defaults.silk_text_size_v" );
392 
393  if( !fromLegacy<double>( aCfg, "SilkTextSizeH", bp + "defaults.silk_text_size_h" ) )
394  fromLegacy<double>( aCfg, "ModuleTextSizeH", bp + "defaults.silk_text_size_h" );
395 
396  if( !fromLegacy<double>( aCfg, "SilkTextSizeThickness", bp + "defaults.silk_text_thickness" ) )
397  fromLegacy<double>( aCfg, "ModuleTextSizeThickness", bp + "defaults.silk_text_thickness" );
398 
399  fromLegacy<bool>( aCfg, "SilkTextItalic", bp + "defaults.silk_text_italic" );
400  fromLegacy<bool>( aCfg, "SilkTextUpright", bp + "defaults.silk_text_upright" );
401 
402  if( !fromLegacy<double>( aCfg, "CopperLineWidth", bp + "defaults.copper_line_width" ) )
403  fromLegacy<double>( aCfg, "DrawSegmentWidth", bp + "defaults.copper_line_width" );
404 
405  if( !fromLegacy<double>( aCfg, "CopperTextSizeV", bp + "defaults.copper_text_size_v" ) )
406  fromLegacy<double>( aCfg, "PcbTextSizeV", bp + "defaults.copper_text_size_v" );
407 
408  if( !fromLegacy<double>( aCfg, "CopperTextSizeH", bp + "defaults.copper_text_size_h" ) )
409  fromLegacy<double>( aCfg, "PcbTextSizeH", bp + "defaults.copper_text_size_h" );
410 
411  if( !fromLegacy<double>( aCfg, "CopperTextThickness", bp + "defaults.copper_text_thickness" ) )
412  fromLegacy<double>( aCfg, "PcbTextThickness", bp + "defaults.copper_text_thickness" );
413 
414  fromLegacy<bool>( aCfg, "CopperTextItalic", bp + "defaults.copper_text_italic" );
415  fromLegacy<bool>( aCfg, "CopperTextUpright", bp + "defaults.copper_text_upright" );
416 
417  if( !fromLegacy<double>( aCfg, "EdgeCutLineWidth", bp + "defaults.board_outline_line_width" ) )
418  fromLegacy<double>(
419  aCfg, "BoardOutlineThickness", bp + "defaults.board_outline_line_width" );
420 
421  fromLegacy<double>( aCfg, "CourtyardLineWidth", bp + "defaults.courtyard_line_width" );
422 
423  fromLegacy<double>( aCfg, "FabLineWidth", bp + "defaults.fab_line_width" );
424  fromLegacy<double>( aCfg, "FabTextSizeV", bp + "defaults.fab_text_size_v" );
425  fromLegacy<double>( aCfg, "FabTextSizeH", bp + "defaults.fab_text_size_h" );
426  fromLegacy<double>( aCfg, "FabTextSizeThickness", bp + "defaults.fab_text_thickness" );
427  fromLegacy<bool>( aCfg, "FabTextItalic", bp + "defaults.fab_text_italic" );
428  fromLegacy<bool>( aCfg, "FabTextUpright", bp + "defaults.fab_text_upright" );
429 
430  if( !fromLegacy<double>( aCfg, "OthersLineWidth", bp + "defaults.other_line_width" ) )
431  fromLegacy<double>( aCfg, "ModuleOutlineThickness", bp + "defaults.other_line_width" );
432 
433  fromLegacy<double>( aCfg, "OthersTextSizeV", bp + "defaults.other_text_size_v" );
434  fromLegacy<double>( aCfg, "OthersTextSizeH", bp + "defaults.other_text_size_h" );
435  fromLegacy<double>( aCfg, "OthersTextSizeThickness", bp + "defaults.other_text_thickness" );
436  fromLegacy<bool>( aCfg, "OthersTextItalic", bp + "defaults.other_text_italic" );
437  fromLegacy<bool>( aCfg, "OthersTextUpright", bp + "defaults.other_text_upright" );
438 
439  fromLegacy<int>( aCfg, "DimensionUnits", bp + "defaults.dimension_units" );
440  fromLegacy<int>( aCfg, "DimensionPrecision", bp + "defaults.dimension_precision" );
441 
442  std::string sev = bp + "rule_severities";
443 
444  fromLegacy<bool>(
445  aCfg, "RequireCourtyardDefinitions", sev + "legacy_no_courtyard_defined" );
446 
447  fromLegacy<bool>( aCfg, "ProhibitOverlappingCourtyards", sev + "legacy_courtyards_overlap" );
448 
449  {
450  int idx = 1;
451  wxString keyBase = "TrackWidth";
452  wxString key = keyBase;
453  double val;
454 
455  nlohmann::json widths = nlohmann::json::array();
456 
457  key << idx;
458 
459  while( aCfg->Read( key, &val ) )
460  {
461  widths.push_back( val );
462  key = keyBase;
463  key << ++idx;
464  }
465 
466  ( *this )[PointerFromString( bp + "track_widths" )] = widths;
467  }
468 
469  {
470  int idx = 1;
471  wxString keyBase = "ViaDiameter";
472  wxString key = keyBase;
473  double diameter;
474  double drill = 1.0;
475 
476  nlohmann::json vias = nlohmann::json::array();
477 
478  key << idx;
479 
480  while( aCfg->Read( key, &diameter ) )
481  {
482  key = "ViaDrill";
483  aCfg->Read( key << idx, &drill );
484 
485  nlohmann::json via = { { "diameter", diameter }, { "drill", drill } };
486  vias.push_back( via );
487 
488  key = keyBase;
489  key << ++idx;
490  }
491 
492  ( *this )[PointerFromString( bp + "via_dimensions" )] = vias;
493  }
494 
495  {
496  int idx = 1;
497  wxString keyBase = "dPairWidth";
498  wxString key = keyBase;
499  double width;
500  double gap = 1.0;
501  double via_gap = 1.0;
502 
503  nlohmann::json pairs = nlohmann::json::array();
504 
505  key << idx;
506 
507  while( aCfg->Read( key, &width ) )
508  {
509  key = "dPairGap";
510  aCfg->Read( key << idx, &gap );
511 
512  key = "dPairViaGap";
513  aCfg->Read( key << idx, &via_gap );
514 
515  nlohmann::json pair = { { "width", width }, { "gap", gap }, { "via_gap", via_gap } };
516  pairs.push_back( pair );
517 
518  key = keyBase;
519  key << ++idx;
520  }
521 
522  ( *this )[PointerFromString( bp + "diff_pair_dimensions" )] = pairs;
523  }
524 
525  group_blacklist.insert( wxT( "/pcbnew" ) );
526 
527  // General group is unused these days, we can throw it away
528  group_blacklist.insert( wxT( "/general" ) );
529 
530  // Next load sheet names and put all other legacy data in the legacy dict
531  aCfg->SetPath( wxT( "/" ) );
532 
533  auto loadSheetNames =
534  [&]() -> bool
535  {
536  int sheet = 1;
537  wxString entry;
538  nlohmann::json arr = nlohmann::json::array();
539 
540  wxLogTrace( traceSettings, "Migrating sheet names" );
541 
542  aCfg->SetPath( wxT( "/sheetnames" ) );
543 
544  while( aCfg->Read( wxString::Format( "%d", sheet++ ), &entry ) )
545  {
546  wxArrayString tokens = wxSplit( entry, ':' );
547 
548  if( tokens.size() == 2 )
549  {
550  wxLogTrace( traceSettings, "%d: %s = %s", sheet, tokens[0], tokens[1] );
551  arr.push_back( nlohmann::json::array( { tokens[0], tokens[1] } ) );
552  }
553  }
554 
555  ( *this )[PointerFromString( "sheets" )] = arr;
556 
557  aCfg->SetPath( "/" );
558 
559  // TODO: any reason we want to fail on this?
560  return true;
561  };
562 
563  std::vector<wxString> groups;
564 
565  groups.emplace_back( "" );
566 
567  auto loadLegacyPairs =
568  [&]( const std::string& aGroup ) -> bool
569  {
570  wxLogTrace( traceSettings, "Migrating group %s", aGroup );
571  bool success = true;
572  wxString keyStr;
573  wxString val;
574 
575  index = 0;
576 
577  while( aCfg->GetNextEntry( keyStr, index ) )
578  {
579  if( !aCfg->Read( keyStr, &val ) )
580  continue;
581 
582  std::string key( keyStr.ToUTF8() );
583 
584  wxLogTrace( traceSettings, " %s = %s", key, val );
585 
586  try
587  {
588  nlohmann::json::json_pointer ptr( "/legacy" + aGroup + "/" + key );
589  ( *this )[ptr] = val;
590  }
591  catch( ... )
592  {
593  success = false;
594  }
595  }
596 
597  return success;
598  };
599 
600  for( size_t i = 0; i < groups.size(); i++ )
601  {
602  aCfg->SetPath( groups[i] );
603 
604  if( groups[i] == wxT( "/sheetnames" ) )
605  {
606  ret |= loadSheetNames();
607  continue;
608  }
609 
610  aCfg->DeleteEntry( wxT( "last_client" ), true );
611  aCfg->DeleteEntry( wxT( "update" ), true );
612  aCfg->DeleteEntry( wxT( "version" ), true );
613 
614  ret &= loadLegacyPairs( groups[i].ToStdString() );
615 
616  index = 0;
617 
618  while( aCfg->GetNextGroup( str, index ) )
619  {
620  wxString group = groups[i] + "/" + str;
621 
622  if( !group_blacklist.count( group ) )
623  groups.emplace_back( group );
624  }
625 
626  aCfg->SetPath( "/" );
627  }
628 
629  return ret;
630 }
631 
632 
633 bool PROJECT_FILE::SaveToFile( const wxString& aDirectory, bool aForce )
634 {
635  wxASSERT( m_project );
636 
637  ( *this )[PointerFromString( "meta.filename" )] =
639 
640  return JSON_SETTINGS::SaveToFile( aDirectory, aForce );
641 }
642 
643 
644 wxString PROJECT_FILE::getFileExt() const
645 {
646  return ProjectFileExtension;
647 }
648 
649 
651 {
653 }
654 
655 
656 void to_json( nlohmann::json& aJson, const FILE_INFO_PAIR& aPair )
657 {
658  aJson = nlohmann::json::array( { aPair.first.AsString().ToUTF8(), aPair.second.ToUTF8() } );
659 }
660 
661 
662 void from_json( const nlohmann::json& aJson, FILE_INFO_PAIR& aPair )
663 {
664  wxASSERT( aJson.is_array() && aJson.size() == 2 );
665  aPair.first = KIID( wxString( aJson[0].get<std::string>().c_str(), wxConvUTF8 ) );
666  aPair.second = wxString( aJson[1].get<std::string>().c_str(), wxConvUTF8 );
667 }
PROJECT * m_project
A link to the owning PROJECT.
Definition: project_file.h:111
A saved set of layers that are visible.
std::map< wxString, wxString > m_TextVars
Definition: project_file.h:128
std::vector< wxString > m_PinnedSymbolLibs
Below are project-level settings that have not been moved to a dedicated file.
Definition: project_file.h:123
std::vector< wxString > m_PinnedFootprintLibs
The list of pinned footprint libraries.
Definition: project_file.h:126
std::vector< PARAM_BASE * > m_params
The list of parameters (owned by this object)
PROJECT holds project specific data.
Definition: project.h:61
Like a normal param, but with custom getter and setter functions.
Definition: parameters.h:296
const std::string ProjectFileExtension
wxArrayString m_LegacyLibNames
Definition: project_file.h:154
std::vector< FILE_INFO_PAIR > m_sheets
An list of schematic sheets in this project.
Definition: project_file.h:105
const int projectFileSchemaVersion
! Update the schema version whenever a migration is required
wxString getLegacyFileExt() const override
bool SaveToFile(const wxString &aDirectory="", bool aForce=false) override
SETTINGS_LOC
Definition: json_settings.h:36
GAL_LAYER_ID
GAL layers are "virtual" layers, i.e.
Add new GAL layers here.
wxString m_PcbLastPath[LAST_PATH_SIZE]
MRU path storage.
Definition: project_file.h:171
nlohmann::json json
Definition: gerbview.cpp:40
PCB_LAYER_ID activeLayer
Optional layer to set active when this preset is loaded.
bool m_deleteLegacyAfterMigration
Whether or not to delete legacy file after migration.
Stores a path as a string with directory separators normalized to unix-style.
Definition: parameters.h:173
Definition: common.h:68
std::pair< KIID, wxString > FILE_INFO_PAIR
For files like sheets and boards, a pair of that object KIID and display name Display name is typical...
Definition: project_file.h:33
std::shared_ptr< NET_SETTINGS > m_NetSettings
Net settings for this project (owned here) NOTE: If we go multi-board in the future,...
Definition: project_file.h:186
PCB_LAYER_ID
A quick note on layer IDs:
virtual bool SaveToFile(const wxString &aDirectory="", bool aForce=false)
wxString m_BoardPageLayoutDescrFile
PcbNew params.
Definition: project_file.h:168
std::vector< wxString > m_EquivalenceFiles
CvPcb params.
Definition: project_file.h:161
Definition of file extensions used in Kicad.
wxString getFileExt() const override
LSET layers
Board layers that are visible.
const std::string LegacyProjectFileExtension
bool fromLegacyString(wxConfigBase *aConfig, const std::string &aKey, const std::string &aDest)
Translates a legacy wxConfig string value to a given JSON pointer value.
A helper for <wxString, wxString> maps.
Definition: parameters.h:724
void to_json(nlohmann::json &aJson, const FILE_INFO_PAIR &aPair)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
virtual bool MigrateFromLegacy(wxConfigBase *aCfg) override
Migrates from wxConfig to JSON-based configuration.
void from_json(const nlohmann::json &aJson, FILE_INFO_PAIR &aPair)
wxString m_LegacyLibDir
Definition: project_file.h:152
VTBL_ENTRY const wxString GetProjectName() const
Function GetProjectName returns the short name of the project.
Definition: project.cpp:129
std::vector< LAYER_PRESET > m_LayerPresets
List of stored layer presets.
Definition: project_file.h:189
Represents a list of strings holding directory paths.
Definition: parameters.h:560
const char * traceSettings
Flag to enable settings tracing.
static nlohmann::json::json_pointer PointerFromString(std::string aPath)
Builds a JSON pointer based on a given string.
PROJECT_FILE(const wxString &aFullPath)
Constructs the project file for a project.
std::vector< FILE_INFO_PAIR > m_boards
A list of board files in this project.
Definition: project_file.h:108