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