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