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