34#include <wx/filename.h>
67 [&]() -> nlohmann::json
69 nlohmann::json ret = nlohmann::json::array();
74 ret.push_back( nlohmann::json( {
75 {
"name", field.m_Name },
76 {
"visible", field.m_Visible },
77 {
"url", field.m_URL }
83 [&](
const nlohmann::json& aJson )
85 if( !aJson.empty() && aJson.is_array() )
89 for(
const nlohmann::json& entry : aJson )
91 if( entry.contains(
"name" ) && entry.contains(
"url" )
92 && entry.contains(
"visible" ) )
95 field.
m_URL = entry[
"url"].get<
bool>();
96 field.
m_Visible = entry[
"visible"].get<
bool>();
142 [&]() -> nlohmann::json
144 nlohmann::json ret = nlohmann::json::array();
147 ret.push_back( libName );
151 [&](
const nlohmann::json& aJson )
153 if( aJson.empty() || !aJson.is_array() )
158 for(
const nlohmann::json& entry : aJson )
163 [&]() -> nlohmann::json
165 nlohmann::json ret = nlohmann::json::object();
169 nlohmann::json members = nlohmann::json::array();
171 for(
const wxString& member : alias.second )
172 members.push_back( member );
174 ret[ alias.first.ToStdString() ] = members;
179 [&](
const nlohmann::json& aJson )
181 if( !aJson.is_object() )
186 for(
auto it = aJson.begin(); it != aJson.end(); ++it )
188 const nlohmann::json& membersJson = it.value();
190 if( !membersJson.is_array() )
193 std::vector<wxString> members;
195 for(
const nlohmann::json& entry : membersJson )
197 if( entry.is_string() )
199 wxString member = entry.get<wxString>().Strip( wxString::both );
201 if( !member.IsEmpty() )
202 members.push_back( member );
206 wxString
name = wxString::FromUTF8( it.key().c_str() ).Strip( wxString::both );
208 if( !
name.IsEmpty() )
214 m_params.back()->SetClearUnknownKeys();
216 m_NetSettings = std::make_shared<NET_SETTINGS>(
this,
"net_settings" );
219 std::make_shared<COMPONENT_CLASS_SETTINGS>(
this,
"component_class_settings" );
272 auto p(
"/board/layer_presets"_json_pointer );
279 for( nlohmann::json& entry : presets )
290 auto p(
"/board/layer_presets"_json_pointer );
297 for( nlohmann::json& entry : presets )
312 std::set<wxString> group_blacklist;
319 auto loadPinnedLibs =
320 [&](
const std::string& aDest )
323 wxString libKey = wxT(
"PinnedItems" );
326 nlohmann::json libs = nlohmann::json::array();
328 while( aCfg->Read( libKey, &str ) )
330 libs.push_back( str );
332 aCfg->DeleteEntry( libKey,
true );
334 libKey = wxT(
"PinnedItems" );
335 libKey << ++libIndex;
341 aCfg->SetPath( wxT(
"/LibeditFrame" ) );
342 loadPinnedLibs(
"libraries.pinned_symbol_libs" );
344 aCfg->SetPath( wxT(
"/ModEditFrame" ) );
345 loadPinnedLibs(
"libraries.pinned_footprint_libs" );
347 aCfg->SetPath( wxT(
"/cvpcb/equfiles" ) );
351 wxString eqKey = wxT(
"EquName" );
354 nlohmann::json eqs = nlohmann::json::array();
356 while( aCfg->Read( eqKey, &str ) )
358 eqs.push_back( str );
360 eqKey = wxT(
"EquName" );
364 Set(
"cvpcb.equivalence_files", eqs );
368 group_blacklist.insert( wxT(
"/cvpcb" ) );
370 aCfg->SetPath( wxT(
"/eeschema" ) );
373 aCfg->SetPath( wxT(
"/eeschema/libraries" ) );
377 wxString libKey = wxT(
"LibName" );
380 nlohmann::json libs = nlohmann::json::array();
382 while( aCfg->Read( libKey, &str ) )
384 libs.push_back( str );
386 libKey = wxT(
"LibName" );
390 Set(
"schematic.legacy_lib_list", libs );
393 group_blacklist.insert( wxT(
"/eeschema" ) );
395 aCfg->SetPath( wxT(
"/text_variables" ) );
402 nlohmann::json vars = nlohmann::json();
404 while( aCfg->Read( txtKey, &str ) )
406 wxArrayString tokens = wxSplit( str,
':' );
408 if( tokens.size() == 2 )
409 vars[ tokens[0].ToStdString() ] = tokens[1];
415 Set(
"text_variables", vars );
418 group_blacklist.insert( wxT(
"/text_variables" ) );
420 aCfg->SetPath( wxT(
"/schematic_editor" ) );
422 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"schematic.page_layout_descr_file" );
425 fromLegacy<bool>( aCfg,
"SpiceAjustPassiveValues",
"schematic.spice_adjust_passive_values" );
426 fromLegacy<int>( aCfg,
"SubpartIdSeparator",
"schematic.subpart_id_separator" );
427 fromLegacy<int>( aCfg,
"SubpartFirstId",
"schematic.subpart_first_id" );
429 fromLegacy<int>( aCfg,
"LineThickness",
"schematic.drawing.default_line_thickness" );
430 fromLegacy<int>( aCfg,
"WireThickness",
"schematic.drawing.default_wire_thickness" );
431 fromLegacy<int>( aCfg,
"BusThickness",
"schematic.drawing.default_bus_thickness" );
432 fromLegacy<int>( aCfg,
"LabSize",
"schematic.drawing.default_text_size" );
434 if( !
fromLegacy<int>( aCfg,
"PinSymbolSize",
"schematic.drawing.pin_symbol_size" ) )
437 Set(
"schematic.drawing.pin_symbol_size", 0 );
440 fromLegacy<int>( aCfg,
"JunctionSize",
"schematic.drawing.default_junction_size" );
442 fromLegacyString( aCfg,
"FieldNameTemplates",
"schematic.drawing.field_names" );
444 if( !
fromLegacy<double>( aCfg,
"TextOffsetRatio",
"schematic.drawing.text_offset_ratio" ) )
447 Set(
"schematic.drawing.text_offset_ratio", 0.08 );
448 Set(
"schematic.drawing.label_size_ratio", 0.25 );
452 group_blacklist.insert( wxT(
"/schematic_editor" ) );
454 aCfg->SetPath( wxT(
"/pcbnew" ) );
456 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"pcbnew.page_layout_descr_file" );
461 fromLegacyString( aCfg,
"LastSpecctraDSNExportPath",
"pcbnew.last_paths.specctra_dsn" );
462 fromLegacyString( aCfg,
"LastGenCADExportPath",
"pcbnew.last_paths.gencad" );
464 std::string bp =
"board.design_settings.";
468 wxString key = wxT(
"DRCExclusion" );
471 nlohmann::json exclusions = nlohmann::json::array();
473 while( aCfg->Read( key, &str ) )
475 exclusions.push_back( str );
477 key = wxT(
"DRCExclusion" );
481 Set( bp +
"drc_exclusions", exclusions );
485 fromLegacy<bool>( aCfg,
"AllowBlindVias", bp +
"rules.allow_blind_buried_vias" );
491 if( !
fromLegacy<double>( aCfg,
"MinThroughDrill", bp +
"rules.min_through_hole_diameter" ) )
494 fromLegacy<double>( aCfg,
"MinMicroViaDiameter", bp +
"rules.min_microvia_diameter" );
497 fromLegacy<double>( aCfg,
"CopperEdgeClearance", bp +
"rules.min_copper_edge_clearance" );
498 fromLegacy<double>( aCfg,
"SolderMaskClearance", bp +
"rules.solder_mask_clearance" );
500 fromLegacy<double>( aCfg,
"SolderPasteClearance", bp +
"rules.solder_paste_clearance" );
501 fromLegacy<double>( aCfg,
"SolderPasteRatio", bp +
"rules.solder_paste_margin_ratio" );
504 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.silk_line_width" );
512 if( !
fromLegacy<double>( aCfg,
"SilkTextSizeThickness", bp +
"defaults.silk_text_thickness" ) )
513 fromLegacy<double>( aCfg,
"ModuleTextSizeThickness", bp +
"defaults.silk_text_thickness" );
515 fromLegacy<bool>( aCfg,
"SilkTextItalic", bp +
"defaults.silk_text_italic" );
516 fromLegacy<bool>( aCfg,
"SilkTextUpright", bp +
"defaults.silk_text_upright" );
518 if( !
fromLegacy<double>( aCfg,
"CopperLineWidth", bp +
"defaults.copper_line_width" ) )
521 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeV", bp +
"defaults.copper_text_size_v" ) )
524 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeH", bp +
"defaults.copper_text_size_h" ) )
527 if( !
fromLegacy<double>( aCfg,
"CopperTextThickness", bp +
"defaults.copper_text_thickness" ) )
528 fromLegacy<double>( aCfg,
"PcbTextThickness", bp +
"defaults.copper_text_thickness" );
530 fromLegacy<bool>( aCfg,
"CopperTextItalic", bp +
"defaults.copper_text_italic" );
531 fromLegacy<bool>( aCfg,
"CopperTextUpright", bp +
"defaults.copper_text_upright" );
533 if( !
fromLegacy<double>( aCfg,
"EdgeCutLineWidth", bp +
"defaults.board_outline_line_width" ) )
535 bp +
"defaults.board_outline_line_width" );
537 fromLegacy<double>( aCfg,
"CourtyardLineWidth", bp +
"defaults.courtyard_line_width" );
542 fromLegacy<double>( aCfg,
"FabTextSizeThickness", bp +
"defaults.fab_text_thickness" );
544 fromLegacy<bool>( aCfg,
"FabTextUpright", bp +
"defaults.fab_text_upright" );
546 if( !
fromLegacy<double>( aCfg,
"OthersLineWidth", bp +
"defaults.other_line_width" ) )
547 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.other_line_width" );
551 fromLegacy<double>( aCfg,
"OthersTextSizeThickness", bp +
"defaults.other_text_thickness" );
552 fromLegacy<bool>( aCfg,
"OthersTextItalic", bp +
"defaults.other_text_italic" );
553 fromLegacy<bool>( aCfg,
"OthersTextUpright", bp +
"defaults.other_text_upright" );
555 fromLegacy<int>( aCfg,
"DimensionUnits", bp +
"defaults.dimension_units" );
556 fromLegacy<int>( aCfg,
"DimensionPrecision", bp +
"defaults.dimension_precision" );
558 std::string sev = bp +
"rule_severities";
560 fromLegacy<bool>( aCfg,
"RequireCourtyardDefinitions", sev +
"legacy_no_courtyard_defined" );
562 fromLegacy<bool>( aCfg,
"ProhibitOverlappingCourtyards", sev +
"legacy_courtyards_overlap" );
566 wxString keyBase =
"TrackWidth";
567 wxString key = keyBase;
570 nlohmann::json widths = nlohmann::json::array();
574 while( aCfg->Read( key, &val ) )
576 widths.push_back( val );
581 Set( bp +
"track_widths", widths );
586 wxString keyBase =
"ViaDiameter";
587 wxString key = keyBase;
591 nlohmann::json vias = nlohmann::json::array();
595 while( aCfg->Read( key, &diameter ) )
598 aCfg->Read( key << idx, &drill );
600 nlohmann::json
via = { {
"diameter", diameter }, {
"drill", drill } };
601 vias.push_back(
via );
607 Set( bp +
"via_dimensions", vias );
612 wxString keyBase =
"dPairWidth";
613 wxString key = keyBase;
616 double via_gap = 1.0;
618 nlohmann::json pairs = nlohmann::json::array();
622 while( aCfg->Read( key, &width ) )
625 aCfg->Read( key << idx, &gap );
628 aCfg->Read( key << idx, &via_gap );
630 nlohmann::json pair = { {
"width", width }, {
"gap", gap }, {
"via_gap", via_gap } };
631 pairs.push_back( pair );
637 Set( bp +
"diff_pair_dimensions", pairs );
640 group_blacklist.insert( wxT(
"/pcbnew" ) );
643 group_blacklist.insert( wxT(
"/general" ) );
646 aCfg->SetPath( wxT(
"/" ) );
648 auto loadSheetNames =
653 nlohmann::json arr = nlohmann::json::array();
657 aCfg->SetPath( wxT(
"/sheetnames" ) );
659 while( aCfg->Read( wxString::Format(
"%d", sheet++ ), &entry ) )
661 wxArrayString tokens = wxSplit( entry,
':' );
663 if( tokens.size() == 2 )
665 wxLogTrace(
traceSettings, wxT(
"%d: %s = %s" ), sheet, tokens[0],
667 arr.push_back( nlohmann::json::array( { tokens[0], tokens[1] } ) );
671 Set(
"sheets", arr );
673 aCfg->SetPath(
"/" );
678 std::vector<wxString> groups;
680 groups.emplace_back( wxEmptyString );
682 auto loadLegacyPairs =
683 [&](
const std::string& aGroup ) ->
bool
685 wxLogTrace(
traceSettings, wxT(
"Migrating group %s" ), aGroup );
692 while( aCfg->GetNextEntry( keyStr,
index ) )
694 if( !aCfg->Read( keyStr, &val ) )
697 std::string key( keyStr.ToUTF8() );
703 Set(
"legacy." + aGroup +
"." + key, val );
714 for(
size_t i = 0; i < groups.size(); i++ )
716 aCfg->SetPath( groups[i] );
718 if( groups[i] == wxT(
"/sheetnames" ) )
720 ret |= loadSheetNames();
724 aCfg->DeleteEntry( wxT(
"last_client" ),
true );
725 aCfg->DeleteEntry( wxT(
"update" ),
true );
726 aCfg->DeleteEntry( wxT(
"version" ),
true );
732 while( aCfg->GetNextGroup( str,
index ) )
734 wxString
group = groups[i] +
"/" + str;
736 if( !group_blacklist.count(
group ) )
737 groups.emplace_back(
group );
740 aCfg->SetPath(
"/" );
757 wxString projectName =
m_project->GetProjectName();
761 defaultSheet.
name = projectName;
762 defaultSheet.
filename = projectName +
".kicad_sch";
769 wxLogTrace(
traceSettings, wxT(
"PROJECT_FILE: Migrated old single-root format to top_level_sheets" ) );
778 wxString projectPath =
m_project->GetProjectPath();
779 wxString projectName =
m_project->GetProjectName();
783 wxFileName referencedFile( projectPath, sheetInfo.filename );
785 if( referencedFile.FileExists() )
789 wxString expectedFile =
792 wxFileName candidateFile( projectPath, expectedFile );
794 if( candidateFile.FileExists() )
797 wxT(
"PROJECT_FILE: Fixing stale top_level_sheets reference "
799 sheetInfo.filename, expectedFile );
801 sheetInfo.filename = expectedFile;
802 sheetInfo.name = projectName;
833 wxString oldProjectName = oldFilename.GetName();
834 wxString oldProjectPath = oldFilename.GetPath();
840 [&]( wxString& aPath )
842 if( aPath.StartsWith( oldProjectName + wxS(
"." ) ) )
843 aPath.Replace( oldProjectName, aFile,
false );
844 else if( aPath.StartsWith( oldProjectPath + wxS(
"/" ) ) )
845 aPath.Replace( oldProjectPath, aDirectory,
false );
853 auto updatePathByPtr =
854 [&](
const std::string& aPtr )
858 updatePath(
path.value() );
863 updatePathByPtr(
"schematic.page_layout_descr_file" );
864 updatePathByPtr(
"schematic.plot_directory" );
865 updatePathByPtr(
"schematic.ngspice.workbook_filename" );
866 updatePathByPtr(
"pcbnew.page_layout_descr_file" );
870 updatePath( sheetInfo.filename );
873 if( sheetInfo.name == oldProjectName )
874 sheetInfo.name = aFile;
902 aJson = nlohmann::json::array( { aPair.first.AsString().ToUTF8(), aPair.second.ToUTF8() } );
908 wxCHECK( aJson.is_array() && aJson.size() == 2, );
909 aPair.first =
KIID( wxString( aJson[0].get<std::string>().c_str(), wxConvUTF8 ) );
910 aPair.second = wxString( aJson[1].get<std::string>().c_str(), wxConvUTF8 );
916 aJson = nlohmann::json::object();
918 aJson[
"name"] = aInfo.
name.ToUTF8();
919 aJson[
"filename"] = aInfo.
filename.ToUTF8();
925 wxCHECK( aJson.is_object(), );
927 if( aJson.contains(
"uuid" ) )
928 aInfo.
uuid =
KIID( wxString( aJson[
"uuid"].get<std::string>().c_str(), wxConvUTF8 ) );
930 if( aJson.contains(
"name" ) )
931 aInfo.
name = wxString( aJson[
"name"].get<std::string>().c_str(), wxConvUTF8 );
933 if( aJson.contains(
"filename" ) )
934 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.
TEMPLATES m_TemplateFieldNames
Project and global field name templates shared by project editors.
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.
std::vector< wxString > m_PinnedDesignBlockLibs
The list of pinned design block libraries.
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.
std::vector< wxString > m_FindByPropertiesQueries
Recent queries for Find by Properties dialog.
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 std::string ToStdString(const wxString &aStr)
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...
Hold a name of a symbol's field, field value, and default visibility.
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.