34#include <wx/filename.h>
97 [&]() -> nlohmann::json
99 nlohmann::json ret = nlohmann::json::array();
102 ret.push_back( libName );
106 [&](
const nlohmann::json& aJson )
108 if( aJson.empty() || !aJson.is_array() )
113 for(
const nlohmann::json& entry : aJson )
118 [&]() -> nlohmann::json
120 nlohmann::json ret = nlohmann::json::object();
124 nlohmann::json members = nlohmann::json::array();
126 for(
const wxString& member : alias.second )
127 members.push_back( member );
129 ret[ alias.first.ToStdString() ] = members;
134 [&](
const nlohmann::json& aJson )
136 if( aJson.empty() || !aJson.is_object() )
141 for(
auto it = aJson.begin(); it != aJson.end(); ++it )
143 const nlohmann::json& membersJson = it.value();
145 if( !membersJson.is_array() )
148 std::vector<wxString> members;
150 for(
const nlohmann::json& entry : membersJson )
152 if( entry.is_string() )
154 wxString member = entry.get<wxString>().Strip( wxString::both );
156 if( !member.IsEmpty() )
157 members.push_back( member );
161 wxString
name = wxString::FromUTF8( it.key().c_str() ).Strip( wxString::both );
163 if( !
name.IsEmpty() )
168 m_NetSettings = std::make_shared<NET_SETTINGS>(
this,
"net_settings" );
171 std::make_shared<COMPONENT_CLASS_SETTINGS>(
this,
"component_class_settings" );
206 auto p(
"/board/layer_presets"_json_pointer );
213 for( nlohmann::json& entry : presets )
224 auto p(
"/board/layer_presets"_json_pointer );
231 for( nlohmann::json& entry : presets )
246 std::set<wxString> group_blacklist;
253 auto loadPinnedLibs =
254 [&](
const std::string& aDest )
257 wxString libKey = wxT(
"PinnedItems" );
260 nlohmann::json libs = nlohmann::json::array();
262 while( aCfg->Read( libKey, &str ) )
264 libs.push_back( str );
266 aCfg->DeleteEntry( libKey,
true );
268 libKey = wxT(
"PinnedItems" );
269 libKey << ++libIndex;
275 aCfg->SetPath( wxT(
"/LibeditFrame" ) );
276 loadPinnedLibs(
"libraries.pinned_symbol_libs" );
278 aCfg->SetPath( wxT(
"/ModEditFrame" ) );
279 loadPinnedLibs(
"libraries.pinned_footprint_libs" );
281 aCfg->SetPath( wxT(
"/cvpcb/equfiles" ) );
285 wxString eqKey = wxT(
"EquName" );
288 nlohmann::json eqs = nlohmann::json::array();
290 while( aCfg->Read( eqKey, &str ) )
292 eqs.push_back( str );
294 eqKey = wxT(
"EquName" );
298 Set(
"cvpcb.equivalence_files", eqs );
302 group_blacklist.insert( wxT(
"/cvpcb" ) );
304 aCfg->SetPath( wxT(
"/eeschema" ) );
307 aCfg->SetPath( wxT(
"/eeschema/libraries" ) );
311 wxString libKey = wxT(
"LibName" );
314 nlohmann::json libs = nlohmann::json::array();
316 while( aCfg->Read( libKey, &str ) )
318 libs.push_back( str );
320 libKey = wxT(
"LibName" );
324 Set(
"schematic.legacy_lib_list", libs );
327 group_blacklist.insert( wxT(
"/eeschema" ) );
329 aCfg->SetPath( wxT(
"/text_variables" ) );
336 nlohmann::json vars = nlohmann::json();
338 while( aCfg->Read( txtKey, &str ) )
340 wxArrayString tokens = wxSplit( str,
':' );
342 if( tokens.size() == 2 )
343 vars[ tokens[0].ToStdString() ] = tokens[1];
349 Set(
"text_variables", vars );
352 group_blacklist.insert( wxT(
"/text_variables" ) );
354 aCfg->SetPath( wxT(
"/schematic_editor" ) );
356 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"schematic.page_layout_descr_file" );
359 fromLegacy<bool>( aCfg,
"SpiceAjustPassiveValues",
"schematic.spice_adjust_passive_values" );
360 fromLegacy<int>( aCfg,
"SubpartIdSeparator",
"schematic.subpart_id_separator" );
361 fromLegacy<int>( aCfg,
"SubpartFirstId",
"schematic.subpart_first_id" );
363 fromLegacy<int>( aCfg,
"LineThickness",
"schematic.drawing.default_line_thickness" );
364 fromLegacy<int>( aCfg,
"WireThickness",
"schematic.drawing.default_wire_thickness" );
365 fromLegacy<int>( aCfg,
"BusThickness",
"schematic.drawing.default_bus_thickness" );
366 fromLegacy<int>( aCfg,
"LabSize",
"schematic.drawing.default_text_size" );
368 if( !
fromLegacy<int>( aCfg,
"PinSymbolSize",
"schematic.drawing.pin_symbol_size" ) )
371 Set(
"schematic.drawing.pin_symbol_size", 0 );
374 fromLegacy<int>( aCfg,
"JunctionSize",
"schematic.drawing.default_junction_size" );
376 fromLegacyString( aCfg,
"FieldNameTemplates",
"schematic.drawing.field_names" );
378 if( !
fromLegacy<double>( aCfg,
"TextOffsetRatio",
"schematic.drawing.text_offset_ratio" ) )
381 Set(
"schematic.drawing.text_offset_ratio", 0.08 );
382 Set(
"schematic.drawing.label_size_ratio", 0.25 );
386 group_blacklist.insert( wxT(
"/schematic_editor" ) );
388 aCfg->SetPath( wxT(
"/pcbnew" ) );
390 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"pcbnew.page_layout_descr_file" );
395 fromLegacyString( aCfg,
"LastSpecctraDSNExportPath",
"pcbnew.last_paths.specctra_dsn" );
396 fromLegacyString( aCfg,
"LastGenCADExportPath",
"pcbnew.last_paths.gencad" );
398 std::string bp =
"board.design_settings.";
402 wxString key = wxT(
"DRCExclusion" );
405 nlohmann::json exclusions = nlohmann::json::array();
407 while( aCfg->Read( key, &str ) )
409 exclusions.push_back( str );
411 key = wxT(
"DRCExclusion" );
415 Set( bp +
"drc_exclusions", exclusions );
419 fromLegacy<bool>( aCfg,
"AllowBlindVias", bp +
"rules.allow_blind_buried_vias" );
425 if( !
fromLegacy<double>( aCfg,
"MinThroughDrill", bp +
"rules.min_through_hole_diameter" ) )
428 fromLegacy<double>( aCfg,
"MinMicroViaDiameter", bp +
"rules.min_microvia_diameter" );
431 fromLegacy<double>( aCfg,
"CopperEdgeClearance", bp +
"rules.min_copper_edge_clearance" );
432 fromLegacy<double>( aCfg,
"SolderMaskClearance", bp +
"rules.solder_mask_clearance" );
434 fromLegacy<double>( aCfg,
"SolderPasteClearance", bp +
"rules.solder_paste_clearance" );
435 fromLegacy<double>( aCfg,
"SolderPasteRatio", bp +
"rules.solder_paste_margin_ratio" );
438 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.silk_line_width" );
446 if( !
fromLegacy<double>( aCfg,
"SilkTextSizeThickness", bp +
"defaults.silk_text_thickness" ) )
447 fromLegacy<double>( aCfg,
"ModuleTextSizeThickness", bp +
"defaults.silk_text_thickness" );
449 fromLegacy<bool>( aCfg,
"SilkTextItalic", bp +
"defaults.silk_text_italic" );
450 fromLegacy<bool>( aCfg,
"SilkTextUpright", bp +
"defaults.silk_text_upright" );
452 if( !
fromLegacy<double>( aCfg,
"CopperLineWidth", bp +
"defaults.copper_line_width" ) )
455 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeV", bp +
"defaults.copper_text_size_v" ) )
458 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeH", bp +
"defaults.copper_text_size_h" ) )
461 if( !
fromLegacy<double>( aCfg,
"CopperTextThickness", bp +
"defaults.copper_text_thickness" ) )
462 fromLegacy<double>( aCfg,
"PcbTextThickness", bp +
"defaults.copper_text_thickness" );
464 fromLegacy<bool>( aCfg,
"CopperTextItalic", bp +
"defaults.copper_text_italic" );
465 fromLegacy<bool>( aCfg,
"CopperTextUpright", bp +
"defaults.copper_text_upright" );
467 if( !
fromLegacy<double>( aCfg,
"EdgeCutLineWidth", bp +
"defaults.board_outline_line_width" ) )
469 bp +
"defaults.board_outline_line_width" );
471 fromLegacy<double>( aCfg,
"CourtyardLineWidth", bp +
"defaults.courtyard_line_width" );
476 fromLegacy<double>( aCfg,
"FabTextSizeThickness", bp +
"defaults.fab_text_thickness" );
478 fromLegacy<bool>( aCfg,
"FabTextUpright", bp +
"defaults.fab_text_upright" );
480 if( !
fromLegacy<double>( aCfg,
"OthersLineWidth", bp +
"defaults.other_line_width" ) )
481 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.other_line_width" );
485 fromLegacy<double>( aCfg,
"OthersTextSizeThickness", bp +
"defaults.other_text_thickness" );
486 fromLegacy<bool>( aCfg,
"OthersTextItalic", bp +
"defaults.other_text_italic" );
487 fromLegacy<bool>( aCfg,
"OthersTextUpright", bp +
"defaults.other_text_upright" );
489 fromLegacy<int>( aCfg,
"DimensionUnits", bp +
"defaults.dimension_units" );
490 fromLegacy<int>( aCfg,
"DimensionPrecision", bp +
"defaults.dimension_precision" );
492 std::string sev = bp +
"rule_severities";
494 fromLegacy<bool>( aCfg,
"RequireCourtyardDefinitions", sev +
"legacy_no_courtyard_defined" );
496 fromLegacy<bool>( aCfg,
"ProhibitOverlappingCourtyards", sev +
"legacy_courtyards_overlap" );
500 wxString keyBase =
"TrackWidth";
501 wxString key = keyBase;
504 nlohmann::json widths = nlohmann::json::array();
508 while( aCfg->Read( key, &val ) )
510 widths.push_back( val );
515 Set( bp +
"track_widths", widths );
520 wxString keyBase =
"ViaDiameter";
521 wxString key = keyBase;
525 nlohmann::json vias = nlohmann::json::array();
529 while( aCfg->Read( key, &diameter ) )
532 aCfg->Read( key << idx, &drill );
534 nlohmann::json
via = { {
"diameter", diameter }, {
"drill", drill } };
535 vias.push_back(
via );
541 Set( bp +
"via_dimensions", vias );
546 wxString keyBase =
"dPairWidth";
547 wxString key = keyBase;
550 double via_gap = 1.0;
552 nlohmann::json pairs = nlohmann::json::array();
556 while( aCfg->Read( key, &width ) )
559 aCfg->Read( key << idx, &gap );
562 aCfg->Read( key << idx, &via_gap );
564 nlohmann::json pair = { {
"width", width }, {
"gap", gap }, {
"via_gap", via_gap } };
565 pairs.push_back( pair );
571 Set( bp +
"diff_pair_dimensions", pairs );
574 group_blacklist.insert( wxT(
"/pcbnew" ) );
577 group_blacklist.insert( wxT(
"/general" ) );
580 aCfg->SetPath( wxT(
"/" ) );
582 auto loadSheetNames =
587 nlohmann::json arr = nlohmann::json::array();
591 aCfg->SetPath( wxT(
"/sheetnames" ) );
593 while( aCfg->Read( wxString::Format(
"%d", sheet++ ), &entry ) )
595 wxArrayString tokens = wxSplit( entry,
':' );
597 if( tokens.size() == 2 )
599 wxLogTrace(
traceSettings, wxT(
"%d: %s = %s" ), sheet, tokens[0],
601 arr.push_back( nlohmann::json::array( { tokens[0], tokens[1] } ) );
605 Set(
"sheets", arr );
607 aCfg->SetPath(
"/" );
612 std::vector<wxString> groups;
614 groups.emplace_back( wxEmptyString );
616 auto loadLegacyPairs =
617 [&](
const std::string& aGroup ) ->
bool
619 wxLogTrace(
traceSettings, wxT(
"Migrating group %s" ), aGroup );
626 while( aCfg->GetNextEntry( keyStr,
index ) )
628 if( !aCfg->Read( keyStr, &val ) )
631 std::string key( keyStr.ToUTF8() );
637 Set(
"legacy." + aGroup +
"." + key, val );
648 for(
size_t i = 0; i < groups.size(); i++ )
650 aCfg->SetPath( groups[i] );
652 if( groups[i] == wxT(
"/sheetnames" ) )
654 ret |= loadSheetNames();
658 aCfg->DeleteEntry( wxT(
"last_client" ),
true );
659 aCfg->DeleteEntry( wxT(
"update" ),
true );
660 aCfg->DeleteEntry( wxT(
"version" ),
true );
662 ret &= loadLegacyPairs( groups[i].ToStdString() );
666 while( aCfg->GetNextGroup( str,
index ) )
668 wxString
group = groups[i] +
"/" + str;
670 if( !group_blacklist.count(
group ) )
671 groups.emplace_back(
group );
674 aCfg->SetPath(
"/" );
691 wxString projectName =
m_project->GetProjectName();
695 defaultSheet.
name = projectName;
696 defaultSheet.
filename = projectName +
".kicad_sch";
703 wxLogTrace(
traceSettings, wxT(
"PROJECT_FILE: Migrated old single-root format to top_level_sheets" ) );
712 wxString projectPath =
m_project->GetProjectPath();
713 wxString projectName =
m_project->GetProjectName();
717 wxFileName referencedFile( projectPath, sheetInfo.filename );
719 if( referencedFile.FileExists() )
723 wxString expectedFile =
726 wxFileName candidateFile( projectPath, expectedFile );
728 if( candidateFile.FileExists() )
731 wxT(
"PROJECT_FILE: Fixing stale top_level_sheets reference "
733 sheetInfo.filename, expectedFile );
735 sheetInfo.filename = expectedFile;
736 sheetInfo.name = projectName;
767 wxString oldProjectName = oldFilename.GetName();
768 wxString oldProjectPath = oldFilename.GetPath();
774 [&]( wxString& aPath )
776 if( aPath.StartsWith( oldProjectName + wxS(
"." ) ) )
777 aPath.Replace( oldProjectName, aFile,
false );
778 else if( aPath.StartsWith( oldProjectPath + wxS(
"/" ) ) )
779 aPath.Replace( oldProjectPath, aDirectory,
false );
787 auto updatePathByPtr =
788 [&](
const std::string& aPtr )
792 updatePath(
path.value() );
797 updatePathByPtr(
"schematic.page_layout_descr_file" );
798 updatePathByPtr(
"schematic.plot_directory" );
799 updatePathByPtr(
"schematic.ngspice.workbook_filename" );
800 updatePathByPtr(
"pcbnew.page_layout_descr_file" );
804 updatePath( sheetInfo.filename );
807 if( sheetInfo.name == oldProjectName )
808 sheetInfo.name = aFile;
836 aJson = nlohmann::json::array( { aPair.first.AsString().ToUTF8(), aPair.second.ToUTF8() } );
842 wxCHECK( aJson.is_array() && aJson.size() == 2, );
843 aPair.first =
KIID( wxString( aJson[0].get<std::string>().c_str(), wxConvUTF8 ) );
844 aPair.second = wxString( aJson[1].get<std::string>().c_str(), wxConvUTF8 );
850 aJson = nlohmann::json::object();
852 aJson[
"name"] = aInfo.
name.ToUTF8();
853 aJson[
"filename"] = aInfo.
filename.ToUTF8();
859 wxCHECK( aJson.is_object(), );
861 if( aJson.contains(
"uuid" ) )
862 aInfo.
uuid =
KIID( wxString( aJson[
"uuid"].get<std::string>().c_str(), wxConvUTF8 ) );
864 if( aJson.contains(
"name" ) )
865 aInfo.
name = wxString( aJson[
"name"].get<std::string>().c_str(), wxConvUTF8 );
867 if( aJson.contains(
"filename" ) )
868 aInfo.
filename = wxString( aJson[
"filename"].get<std::string>().c_str(), wxConvUTF8 );
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...
virtual bool LoadFromFile(const wxString &aDirectory="")
Loads the backing file from disk and then calls Load()
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
wxString AsString() const
Like a normal param, but with custom getter and setter functions.
static void MigrateToV9Layers(nlohmann::json &aJson)
static void MigrateToNamedRenderLayers(nlohmann::json &aJson)
Represents a list of strings holding directory paths.
Stores a path as a string with directory separators normalized to unix-style.
A helper for <wxString, wxString> maps.
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.
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::vector< TOP_LEVEL_SHEET_INFO > m_topLevelSheets
A list of top-level schematic sheets in 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::map< wxString, std::vector< wxString > > m_BusAliases
Bus alias definitions for the schematic project.
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.
bool LoadFromFile(const wxString &aDirectory="") override
Loads the backing file from disk and then calls Load()
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.
std::shared_ptr< TUNING_PROFILES > m_tuningProfileParameters
Tuning profile parameters for 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.
static const std::string ProjectFileExtension
static const std::string LegacyProjectFileExtension
static const std::string KiCadSchematicFileExtension
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
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...
Information about a top-level schematic sheet.
KIID uuid
Unique identifier for the sheet.
wxString name
Display name for the sheet.
wxString filename
Relative path to the sheet file.
Definition of file extensions used in Kicad.