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" );
212 auto p(
"/board/layer_presets"_json_pointer );
219 for( nlohmann::json& entry : presets )
230 auto p(
"/board/layer_presets"_json_pointer );
237 for( nlohmann::json& entry : presets )
252 std::set<wxString> group_blacklist;
259 auto loadPinnedLibs =
260 [&](
const std::string& aDest )
263 wxString libKey = wxT(
"PinnedItems" );
266 nlohmann::json libs = nlohmann::json::array();
268 while( aCfg->Read( libKey, &str ) )
270 libs.push_back( str );
272 aCfg->DeleteEntry( libKey,
true );
274 libKey = wxT(
"PinnedItems" );
275 libKey << ++libIndex;
281 aCfg->SetPath( wxT(
"/LibeditFrame" ) );
282 loadPinnedLibs(
"libraries.pinned_symbol_libs" );
284 aCfg->SetPath( wxT(
"/ModEditFrame" ) );
285 loadPinnedLibs(
"libraries.pinned_footprint_libs" );
287 aCfg->SetPath( wxT(
"/cvpcb/equfiles" ) );
291 wxString eqKey = wxT(
"EquName" );
294 nlohmann::json eqs = nlohmann::json::array();
296 while( aCfg->Read( eqKey, &str ) )
298 eqs.push_back( str );
300 eqKey = wxT(
"EquName" );
304 Set(
"cvpcb.equivalence_files", eqs );
308 group_blacklist.insert( wxT(
"/cvpcb" ) );
310 aCfg->SetPath( wxT(
"/eeschema" ) );
313 aCfg->SetPath( wxT(
"/eeschema/libraries" ) );
317 wxString libKey = wxT(
"LibName" );
320 nlohmann::json libs = nlohmann::json::array();
322 while( aCfg->Read( libKey, &str ) )
324 libs.push_back( str );
326 libKey = wxT(
"LibName" );
330 Set(
"schematic.legacy_lib_list", libs );
333 group_blacklist.insert( wxT(
"/eeschema" ) );
335 aCfg->SetPath( wxT(
"/text_variables" ) );
342 nlohmann::json vars = nlohmann::json();
344 while( aCfg->Read( txtKey, &str ) )
346 wxArrayString tokens = wxSplit( str,
':' );
348 if( tokens.size() == 2 )
349 vars[ tokens[0].ToStdString() ] = tokens[1];
355 Set(
"text_variables", vars );
358 group_blacklist.insert( wxT(
"/text_variables" ) );
360 aCfg->SetPath( wxT(
"/schematic_editor" ) );
362 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"schematic.page_layout_descr_file" );
365 fromLegacy<bool>( aCfg,
"SpiceAjustPassiveValues",
"schematic.spice_adjust_passive_values" );
366 fromLegacy<int>( aCfg,
"SubpartIdSeparator",
"schematic.subpart_id_separator" );
367 fromLegacy<int>( aCfg,
"SubpartFirstId",
"schematic.subpart_first_id" );
369 fromLegacy<int>( aCfg,
"LineThickness",
"schematic.drawing.default_line_thickness" );
370 fromLegacy<int>( aCfg,
"WireThickness",
"schematic.drawing.default_wire_thickness" );
371 fromLegacy<int>( aCfg,
"BusThickness",
"schematic.drawing.default_bus_thickness" );
372 fromLegacy<int>( aCfg,
"LabSize",
"schematic.drawing.default_text_size" );
374 if( !
fromLegacy<int>( aCfg,
"PinSymbolSize",
"schematic.drawing.pin_symbol_size" ) )
377 Set(
"schematic.drawing.pin_symbol_size", 0 );
380 fromLegacy<int>( aCfg,
"JunctionSize",
"schematic.drawing.default_junction_size" );
382 fromLegacyString( aCfg,
"FieldNameTemplates",
"schematic.drawing.field_names" );
384 if( !
fromLegacy<double>( aCfg,
"TextOffsetRatio",
"schematic.drawing.text_offset_ratio" ) )
387 Set(
"schematic.drawing.text_offset_ratio", 0.08 );
388 Set(
"schematic.drawing.label_size_ratio", 0.25 );
392 group_blacklist.insert( wxT(
"/schematic_editor" ) );
394 aCfg->SetPath( wxT(
"/pcbnew" ) );
396 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"pcbnew.page_layout_descr_file" );
401 fromLegacyString( aCfg,
"LastSpecctraDSNExportPath",
"pcbnew.last_paths.specctra_dsn" );
402 fromLegacyString( aCfg,
"LastGenCADExportPath",
"pcbnew.last_paths.gencad" );
404 std::string bp =
"board.design_settings.";
408 wxString key = wxT(
"DRCExclusion" );
411 nlohmann::json exclusions = nlohmann::json::array();
413 while( aCfg->Read( key, &str ) )
415 exclusions.push_back( str );
417 key = wxT(
"DRCExclusion" );
421 Set( bp +
"drc_exclusions", exclusions );
425 fromLegacy<bool>( aCfg,
"AllowBlindVias", bp +
"rules.allow_blind_buried_vias" );
431 if( !
fromLegacy<double>( aCfg,
"MinThroughDrill", bp +
"rules.min_through_hole_diameter" ) )
434 fromLegacy<double>( aCfg,
"MinMicroViaDiameter", bp +
"rules.min_microvia_diameter" );
437 fromLegacy<double>( aCfg,
"CopperEdgeClearance", bp +
"rules.min_copper_edge_clearance" );
438 fromLegacy<double>( aCfg,
"SolderMaskClearance", bp +
"rules.solder_mask_clearance" );
440 fromLegacy<double>( aCfg,
"SolderPasteClearance", bp +
"rules.solder_paste_clearance" );
441 fromLegacy<double>( aCfg,
"SolderPasteRatio", bp +
"rules.solder_paste_margin_ratio" );
444 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.silk_line_width" );
452 if( !
fromLegacy<double>( aCfg,
"SilkTextSizeThickness", bp +
"defaults.silk_text_thickness" ) )
453 fromLegacy<double>( aCfg,
"ModuleTextSizeThickness", bp +
"defaults.silk_text_thickness" );
455 fromLegacy<bool>( aCfg,
"SilkTextItalic", bp +
"defaults.silk_text_italic" );
456 fromLegacy<bool>( aCfg,
"SilkTextUpright", bp +
"defaults.silk_text_upright" );
458 if( !
fromLegacy<double>( aCfg,
"CopperLineWidth", bp +
"defaults.copper_line_width" ) )
461 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeV", bp +
"defaults.copper_text_size_v" ) )
464 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeH", bp +
"defaults.copper_text_size_h" ) )
467 if( !
fromLegacy<double>( aCfg,
"CopperTextThickness", bp +
"defaults.copper_text_thickness" ) )
468 fromLegacy<double>( aCfg,
"PcbTextThickness", bp +
"defaults.copper_text_thickness" );
470 fromLegacy<bool>( aCfg,
"CopperTextItalic", bp +
"defaults.copper_text_italic" );
471 fromLegacy<bool>( aCfg,
"CopperTextUpright", bp +
"defaults.copper_text_upright" );
473 if( !
fromLegacy<double>( aCfg,
"EdgeCutLineWidth", bp +
"defaults.board_outline_line_width" ) )
475 bp +
"defaults.board_outline_line_width" );
477 fromLegacy<double>( aCfg,
"CourtyardLineWidth", bp +
"defaults.courtyard_line_width" );
482 fromLegacy<double>( aCfg,
"FabTextSizeThickness", bp +
"defaults.fab_text_thickness" );
484 fromLegacy<bool>( aCfg,
"FabTextUpright", bp +
"defaults.fab_text_upright" );
486 if( !
fromLegacy<double>( aCfg,
"OthersLineWidth", bp +
"defaults.other_line_width" ) )
487 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.other_line_width" );
491 fromLegacy<double>( aCfg,
"OthersTextSizeThickness", bp +
"defaults.other_text_thickness" );
492 fromLegacy<bool>( aCfg,
"OthersTextItalic", bp +
"defaults.other_text_italic" );
493 fromLegacy<bool>( aCfg,
"OthersTextUpright", bp +
"defaults.other_text_upright" );
495 fromLegacy<int>( aCfg,
"DimensionUnits", bp +
"defaults.dimension_units" );
496 fromLegacy<int>( aCfg,
"DimensionPrecision", bp +
"defaults.dimension_precision" );
498 std::string sev = bp +
"rule_severities";
500 fromLegacy<bool>( aCfg,
"RequireCourtyardDefinitions", sev +
"legacy_no_courtyard_defined" );
502 fromLegacy<bool>( aCfg,
"ProhibitOverlappingCourtyards", sev +
"legacy_courtyards_overlap" );
506 wxString keyBase =
"TrackWidth";
507 wxString key = keyBase;
510 nlohmann::json widths = nlohmann::json::array();
514 while( aCfg->Read( key, &val ) )
516 widths.push_back( val );
521 Set( bp +
"track_widths", widths );
526 wxString keyBase =
"ViaDiameter";
527 wxString key = keyBase;
531 nlohmann::json vias = nlohmann::json::array();
535 while( aCfg->Read( key, &diameter ) )
538 aCfg->Read( key << idx, &drill );
540 nlohmann::json
via = { {
"diameter", diameter }, {
"drill", drill } };
541 vias.push_back(
via );
547 Set( bp +
"via_dimensions", vias );
552 wxString keyBase =
"dPairWidth";
553 wxString key = keyBase;
556 double via_gap = 1.0;
558 nlohmann::json pairs = nlohmann::json::array();
562 while( aCfg->Read( key, &width ) )
565 aCfg->Read( key << idx, &gap );
568 aCfg->Read( key << idx, &via_gap );
570 nlohmann::json pair = { {
"width", width }, {
"gap", gap }, {
"via_gap", via_gap } };
571 pairs.push_back( pair );
577 Set( bp +
"diff_pair_dimensions", pairs );
580 group_blacklist.insert( wxT(
"/pcbnew" ) );
583 group_blacklist.insert( wxT(
"/general" ) );
586 aCfg->SetPath( wxT(
"/" ) );
588 auto loadSheetNames =
593 nlohmann::json arr = nlohmann::json::array();
597 aCfg->SetPath( wxT(
"/sheetnames" ) );
599 while( aCfg->Read( wxString::Format(
"%d", sheet++ ), &entry ) )
601 wxArrayString tokens = wxSplit( entry,
':' );
603 if( tokens.size() == 2 )
605 wxLogTrace(
traceSettings, wxT(
"%d: %s = %s" ), sheet, tokens[0],
607 arr.push_back( nlohmann::json::array( { tokens[0], tokens[1] } ) );
611 Set(
"sheets", arr );
613 aCfg->SetPath(
"/" );
618 std::vector<wxString> groups;
620 groups.emplace_back( wxEmptyString );
622 auto loadLegacyPairs =
623 [&](
const std::string& aGroup ) ->
bool
625 wxLogTrace(
traceSettings, wxT(
"Migrating group %s" ), aGroup );
632 while( aCfg->GetNextEntry( keyStr,
index ) )
634 if( !aCfg->Read( keyStr, &val ) )
637 std::string key( keyStr.ToUTF8() );
643 Set(
"legacy." + aGroup +
"." + key, val );
654 for(
size_t i = 0; i < groups.size(); i++ )
656 aCfg->SetPath( groups[i] );
658 if( groups[i] == wxT(
"/sheetnames" ) )
660 ret |= loadSheetNames();
664 aCfg->DeleteEntry( wxT(
"last_client" ),
true );
665 aCfg->DeleteEntry( wxT(
"update" ),
true );
666 aCfg->DeleteEntry( wxT(
"version" ),
true );
668 ret &= loadLegacyPairs( groups[i].ToStdString() );
672 while( aCfg->GetNextGroup( str,
index ) )
674 wxString
group = groups[i] +
"/" + str;
676 if( !group_blacklist.count(
group ) )
677 groups.emplace_back(
group );
680 aCfg->SetPath(
"/" );
697 wxString projectName =
m_project->GetProjectName();
701 defaultSheet.
name = projectName;
702 defaultSheet.
filename = projectName +
".kicad_sch";
709 wxLogTrace(
traceSettings, wxT(
"PROJECT_FILE: Migrated old single-root format to top_level_sheets" ) );
718 wxString projectPath =
m_project->GetProjectPath();
719 wxString projectName =
m_project->GetProjectName();
723 wxFileName referencedFile( projectPath, sheetInfo.filename );
725 if( referencedFile.FileExists() )
729 wxString expectedFile =
732 wxFileName candidateFile( projectPath, expectedFile );
734 if( candidateFile.FileExists() )
737 wxT(
"PROJECT_FILE: Fixing stale top_level_sheets reference "
739 sheetInfo.filename, expectedFile );
741 sheetInfo.filename = expectedFile;
742 sheetInfo.name = projectName;
773 wxString oldProjectName = oldFilename.GetName();
774 wxString oldProjectPath = oldFilename.GetPath();
780 [&]( wxString& aPath )
782 if( aPath.StartsWith( oldProjectName + wxS(
"." ) ) )
783 aPath.Replace( oldProjectName, aFile,
false );
784 else if( aPath.StartsWith( oldProjectPath + wxS(
"/" ) ) )
785 aPath.Replace( oldProjectPath, aDirectory,
false );
793 auto updatePathByPtr =
794 [&](
const std::string& aPtr )
798 updatePath(
path.value() );
803 updatePathByPtr(
"schematic.page_layout_descr_file" );
804 updatePathByPtr(
"schematic.plot_directory" );
805 updatePathByPtr(
"schematic.ngspice.workbook_filename" );
806 updatePathByPtr(
"pcbnew.page_layout_descr_file" );
810 updatePath( sheetInfo.filename );
813 if( sheetInfo.name == oldProjectName )
814 sheetInfo.name = aFile;
842 aJson = nlohmann::json::array( { aPair.first.AsString().ToUTF8(), aPair.second.ToUTF8() } );
848 wxCHECK( aJson.is_array() && aJson.size() == 2, );
849 aPair.first =
KIID( wxString( aJson[0].get<std::string>().c_str(), wxConvUTF8 ) );
850 aPair.second = wxString( aJson[1].get<std::string>().c_str(), wxConvUTF8 );
856 aJson = nlohmann::json::object();
858 aJson[
"name"] = aInfo.
name.ToUTF8();
859 aJson[
"filename"] = aInfo.
filename.ToUTF8();
865 wxCHECK( aJson.is_object(), );
867 if( aJson.contains(
"uuid" ) )
868 aInfo.
uuid =
KIID( wxString( aJson[
"uuid"].get<std::string>().c_str(), wxConvUTF8 ) );
870 if( aJson.contains(
"name" ) )
871 aInfo.
name = wxString( aJson[
"name"].get<std::string>().c_str(), wxConvUTF8 );
873 if( aJson.contains(
"filename" ) )
874 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.