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