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