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