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