34#include <wx/filename.h>
100 [&]() -> nlohmann::json
102 nlohmann::json ret = nlohmann::json::array();
105 ret.push_back( libName );
109 [&](
const nlohmann::json& aJson )
111 if( aJson.empty() || !aJson.is_array() )
116 for(
const nlohmann::json& entry : aJson )
121 [&]() -> nlohmann::json
123 nlohmann::json ret = nlohmann::json::object();
127 nlohmann::json members = nlohmann::json::array();
129 for(
const wxString& member : alias.second )
130 members.push_back( member );
132 ret[ alias.first.ToStdString() ] = members;
137 [&](
const nlohmann::json& aJson )
139 if( aJson.empty() || !aJson.is_object() )
144 for(
auto it = aJson.begin(); it != aJson.end(); ++it )
146 const nlohmann::json& membersJson = it.value();
148 if( !membersJson.is_array() )
151 std::vector<wxString> members;
153 for(
const nlohmann::json& entry : membersJson )
155 if( entry.is_string() )
157 wxString member = entry.get<wxString>().Strip( wxString::both );
159 if( !member.IsEmpty() )
160 members.push_back( member );
164 wxString
name = wxString::FromUTF8( it.key().c_str() ).Strip( wxString::both );
166 if( !
name.IsEmpty() )
171 m_NetSettings = std::make_shared<NET_SETTINGS>(
this,
"net_settings" );
174 std::make_shared<COMPONENT_CLASS_SETTINGS>(
this,
"component_class_settings" );
215 auto p(
"/board/layer_presets"_json_pointer );
222 for( nlohmann::json& entry : presets )
233 auto p(
"/board/layer_presets"_json_pointer );
240 for( nlohmann::json& entry : presets )
255 std::set<wxString> group_blacklist;
262 auto loadPinnedLibs =
263 [&](
const std::string& aDest )
266 wxString libKey = wxT(
"PinnedItems" );
269 nlohmann::json libs = nlohmann::json::array();
271 while( aCfg->Read( libKey, &str ) )
273 libs.push_back( str );
275 aCfg->DeleteEntry( libKey,
true );
277 libKey = wxT(
"PinnedItems" );
278 libKey << ++libIndex;
284 aCfg->SetPath( wxT(
"/LibeditFrame" ) );
285 loadPinnedLibs(
"libraries.pinned_symbol_libs" );
287 aCfg->SetPath( wxT(
"/ModEditFrame" ) );
288 loadPinnedLibs(
"libraries.pinned_footprint_libs" );
290 aCfg->SetPath( wxT(
"/cvpcb/equfiles" ) );
294 wxString eqKey = wxT(
"EquName" );
297 nlohmann::json eqs = nlohmann::json::array();
299 while( aCfg->Read( eqKey, &str ) )
301 eqs.push_back( str );
303 eqKey = wxT(
"EquName" );
307 Set(
"cvpcb.equivalence_files", eqs );
311 group_blacklist.insert( wxT(
"/cvpcb" ) );
313 aCfg->SetPath( wxT(
"/eeschema" ) );
316 aCfg->SetPath( wxT(
"/eeschema/libraries" ) );
320 wxString libKey = wxT(
"LibName" );
323 nlohmann::json libs = nlohmann::json::array();
325 while( aCfg->Read( libKey, &str ) )
327 libs.push_back( str );
329 libKey = wxT(
"LibName" );
333 Set(
"schematic.legacy_lib_list", libs );
336 group_blacklist.insert( wxT(
"/eeschema" ) );
338 aCfg->SetPath( wxT(
"/text_variables" ) );
345 nlohmann::json vars = nlohmann::json();
347 while( aCfg->Read( txtKey, &str ) )
349 wxArrayString tokens = wxSplit( str,
':' );
351 if( tokens.size() == 2 )
352 vars[ tokens[0].ToStdString() ] = tokens[1];
358 Set(
"text_variables", vars );
361 group_blacklist.insert( wxT(
"/text_variables" ) );
363 aCfg->SetPath( wxT(
"/schematic_editor" ) );
365 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"schematic.page_layout_descr_file" );
368 fromLegacy<bool>( aCfg,
"SpiceAjustPassiveValues",
"schematic.spice_adjust_passive_values" );
369 fromLegacy<int>( aCfg,
"SubpartIdSeparator",
"schematic.subpart_id_separator" );
370 fromLegacy<int>( aCfg,
"SubpartFirstId",
"schematic.subpart_first_id" );
372 fromLegacy<int>( aCfg,
"LineThickness",
"schematic.drawing.default_line_thickness" );
373 fromLegacy<int>( aCfg,
"WireThickness",
"schematic.drawing.default_wire_thickness" );
374 fromLegacy<int>( aCfg,
"BusThickness",
"schematic.drawing.default_bus_thickness" );
375 fromLegacy<int>( aCfg,
"LabSize",
"schematic.drawing.default_text_size" );
377 if( !
fromLegacy<int>( aCfg,
"PinSymbolSize",
"schematic.drawing.pin_symbol_size" ) )
380 Set(
"schematic.drawing.pin_symbol_size", 0 );
383 fromLegacy<int>( aCfg,
"JunctionSize",
"schematic.drawing.default_junction_size" );
385 fromLegacyString( aCfg,
"FieldNameTemplates",
"schematic.drawing.field_names" );
387 if( !
fromLegacy<double>( aCfg,
"TextOffsetRatio",
"schematic.drawing.text_offset_ratio" ) )
390 Set(
"schematic.drawing.text_offset_ratio", 0.08 );
391 Set(
"schematic.drawing.label_size_ratio", 0.25 );
395 group_blacklist.insert( wxT(
"/schematic_editor" ) );
397 aCfg->SetPath( wxT(
"/pcbnew" ) );
399 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"pcbnew.page_layout_descr_file" );
404 fromLegacyString( aCfg,
"LastSpecctraDSNExportPath",
"pcbnew.last_paths.specctra_dsn" );
405 fromLegacyString( aCfg,
"LastGenCADExportPath",
"pcbnew.last_paths.gencad" );
407 std::string bp =
"board.design_settings.";
411 wxString key = wxT(
"DRCExclusion" );
414 nlohmann::json exclusions = nlohmann::json::array();
416 while( aCfg->Read( key, &str ) )
418 exclusions.push_back( str );
420 key = wxT(
"DRCExclusion" );
424 Set( bp +
"drc_exclusions", exclusions );
428 fromLegacy<bool>( aCfg,
"AllowBlindVias", bp +
"rules.allow_blind_buried_vias" );
434 if( !
fromLegacy<double>( aCfg,
"MinThroughDrill", bp +
"rules.min_through_hole_diameter" ) )
437 fromLegacy<double>( aCfg,
"MinMicroViaDiameter", bp +
"rules.min_microvia_diameter" );
440 fromLegacy<double>( aCfg,
"CopperEdgeClearance", bp +
"rules.min_copper_edge_clearance" );
441 fromLegacy<double>( aCfg,
"SolderMaskClearance", bp +
"rules.solder_mask_clearance" );
443 fromLegacy<double>( aCfg,
"SolderPasteClearance", bp +
"rules.solder_paste_clearance" );
444 fromLegacy<double>( aCfg,
"SolderPasteRatio", bp +
"rules.solder_paste_margin_ratio" );
447 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.silk_line_width" );
455 if( !
fromLegacy<double>( aCfg,
"SilkTextSizeThickness", bp +
"defaults.silk_text_thickness" ) )
456 fromLegacy<double>( aCfg,
"ModuleTextSizeThickness", bp +
"defaults.silk_text_thickness" );
458 fromLegacy<bool>( aCfg,
"SilkTextItalic", bp +
"defaults.silk_text_italic" );
459 fromLegacy<bool>( aCfg,
"SilkTextUpright", bp +
"defaults.silk_text_upright" );
461 if( !
fromLegacy<double>( aCfg,
"CopperLineWidth", bp +
"defaults.copper_line_width" ) )
464 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeV", bp +
"defaults.copper_text_size_v" ) )
467 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeH", bp +
"defaults.copper_text_size_h" ) )
470 if( !
fromLegacy<double>( aCfg,
"CopperTextThickness", bp +
"defaults.copper_text_thickness" ) )
471 fromLegacy<double>( aCfg,
"PcbTextThickness", bp +
"defaults.copper_text_thickness" );
473 fromLegacy<bool>( aCfg,
"CopperTextItalic", bp +
"defaults.copper_text_italic" );
474 fromLegacy<bool>( aCfg,
"CopperTextUpright", bp +
"defaults.copper_text_upright" );
476 if( !
fromLegacy<double>( aCfg,
"EdgeCutLineWidth", bp +
"defaults.board_outline_line_width" ) )
478 bp +
"defaults.board_outline_line_width" );
480 fromLegacy<double>( aCfg,
"CourtyardLineWidth", bp +
"defaults.courtyard_line_width" );
485 fromLegacy<double>( aCfg,
"FabTextSizeThickness", bp +
"defaults.fab_text_thickness" );
487 fromLegacy<bool>( aCfg,
"FabTextUpright", bp +
"defaults.fab_text_upright" );
489 if( !
fromLegacy<double>( aCfg,
"OthersLineWidth", bp +
"defaults.other_line_width" ) )
490 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.other_line_width" );
494 fromLegacy<double>( aCfg,
"OthersTextSizeThickness", bp +
"defaults.other_text_thickness" );
495 fromLegacy<bool>( aCfg,
"OthersTextItalic", bp +
"defaults.other_text_italic" );
496 fromLegacy<bool>( aCfg,
"OthersTextUpright", bp +
"defaults.other_text_upright" );
498 fromLegacy<int>( aCfg,
"DimensionUnits", bp +
"defaults.dimension_units" );
499 fromLegacy<int>( aCfg,
"DimensionPrecision", bp +
"defaults.dimension_precision" );
501 std::string sev = bp +
"rule_severities";
503 fromLegacy<bool>( aCfg,
"RequireCourtyardDefinitions", sev +
"legacy_no_courtyard_defined" );
505 fromLegacy<bool>( aCfg,
"ProhibitOverlappingCourtyards", sev +
"legacy_courtyards_overlap" );
509 wxString keyBase =
"TrackWidth";
510 wxString key = keyBase;
513 nlohmann::json widths = nlohmann::json::array();
517 while( aCfg->Read( key, &val ) )
519 widths.push_back( val );
524 Set( bp +
"track_widths", widths );
529 wxString keyBase =
"ViaDiameter";
530 wxString key = keyBase;
534 nlohmann::json vias = nlohmann::json::array();
538 while( aCfg->Read( key, &diameter ) )
541 aCfg->Read( key << idx, &drill );
543 nlohmann::json
via = { {
"diameter", diameter }, {
"drill", drill } };
544 vias.push_back(
via );
550 Set( bp +
"via_dimensions", vias );
555 wxString keyBase =
"dPairWidth";
556 wxString key = keyBase;
559 double via_gap = 1.0;
561 nlohmann::json pairs = nlohmann::json::array();
565 while( aCfg->Read( key, &width ) )
568 aCfg->Read( key << idx, &gap );
571 aCfg->Read( key << idx, &via_gap );
573 nlohmann::json pair = { {
"width", width }, {
"gap", gap }, {
"via_gap", via_gap } };
574 pairs.push_back( pair );
580 Set( bp +
"diff_pair_dimensions", pairs );
583 group_blacklist.insert( wxT(
"/pcbnew" ) );
586 group_blacklist.insert( wxT(
"/general" ) );
589 aCfg->SetPath( wxT(
"/" ) );
591 auto loadSheetNames =
596 nlohmann::json arr = nlohmann::json::array();
600 aCfg->SetPath( wxT(
"/sheetnames" ) );
602 while( aCfg->Read( wxString::Format(
"%d", sheet++ ), &entry ) )
604 wxArrayString tokens = wxSplit( entry,
':' );
606 if( tokens.size() == 2 )
608 wxLogTrace(
traceSettings, wxT(
"%d: %s = %s" ), sheet, tokens[0],
610 arr.push_back( nlohmann::json::array( { tokens[0], tokens[1] } ) );
614 Set(
"sheets", arr );
616 aCfg->SetPath(
"/" );
621 std::vector<wxString> groups;
623 groups.emplace_back( wxEmptyString );
625 auto loadLegacyPairs =
626 [&](
const std::string& aGroup ) ->
bool
628 wxLogTrace(
traceSettings, wxT(
"Migrating group %s" ), aGroup );
635 while( aCfg->GetNextEntry( keyStr,
index ) )
637 if( !aCfg->Read( keyStr, &val ) )
640 std::string key( keyStr.ToUTF8() );
646 Set(
"legacy." + aGroup +
"." + key, val );
657 for(
size_t i = 0; i < groups.size(); i++ )
659 aCfg->SetPath( groups[i] );
661 if( groups[i] == wxT(
"/sheetnames" ) )
663 ret |= loadSheetNames();
667 aCfg->DeleteEntry( wxT(
"last_client" ),
true );
668 aCfg->DeleteEntry( wxT(
"update" ),
true );
669 aCfg->DeleteEntry( wxT(
"version" ),
true );
671 ret &= loadLegacyPairs( groups[i].ToStdString() );
675 while( aCfg->GetNextGroup( str,
index ) )
677 wxString
group = groups[i] +
"/" + str;
679 if( !group_blacklist.count(
group ) )
680 groups.emplace_back(
group );
683 aCfg->SetPath(
"/" );
700 wxString projectName =
m_project->GetProjectName();
704 defaultSheet.
name = projectName;
705 defaultSheet.
filename = projectName +
".kicad_sch";
712 wxLogTrace(
traceSettings, wxT(
"PROJECT_FILE: Migrated old single-root format to top_level_sheets" ) );
721 wxString projectPath =
m_project->GetProjectPath();
722 wxString projectName =
m_project->GetProjectName();
726 wxFileName referencedFile( projectPath, sheetInfo.filename );
728 if( referencedFile.FileExists() )
732 wxString expectedFile =
735 wxFileName candidateFile( projectPath, expectedFile );
737 if( candidateFile.FileExists() )
740 wxT(
"PROJECT_FILE: Fixing stale top_level_sheets reference "
742 sheetInfo.filename, expectedFile );
744 sheetInfo.filename = expectedFile;
745 sheetInfo.name = projectName;
776 wxString oldProjectName = oldFilename.GetName();
777 wxString oldProjectPath = oldFilename.GetPath();
783 [&]( wxString& aPath )
785 if( aPath.StartsWith( oldProjectName + wxS(
"." ) ) )
786 aPath.Replace( oldProjectName, aFile,
false );
787 else if( aPath.StartsWith( oldProjectPath + wxS(
"/" ) ) )
788 aPath.Replace( oldProjectPath, aDirectory,
false );
796 auto updatePathByPtr =
797 [&](
const std::string& aPtr )
801 updatePath(
path.value() );
806 updatePathByPtr(
"schematic.page_layout_descr_file" );
807 updatePathByPtr(
"schematic.plot_directory" );
808 updatePathByPtr(
"schematic.ngspice.workbook_filename" );
809 updatePathByPtr(
"pcbnew.page_layout_descr_file" );
813 updatePath( sheetInfo.filename );
816 if( sheetInfo.name == oldProjectName )
817 sheetInfo.name = aFile;
845 aJson = nlohmann::json::array( { aPair.first.AsString().ToUTF8(), aPair.second.ToUTF8() } );
851 wxCHECK( aJson.is_array() && aJson.size() == 2, );
852 aPair.first =
KIID( wxString( aJson[0].get<std::string>().c_str(), wxConvUTF8 ) );
853 aPair.second = wxString( aJson[1].get<std::string>().c_str(), wxConvUTF8 );
859 aJson = nlohmann::json::object();
861 aJson[
"name"] = aInfo.
name.ToUTF8();
862 aJson[
"filename"] = aInfo.
filename.ToUTF8();
868 wxCHECK( aJson.is_object(), );
870 if( aJson.contains(
"uuid" ) )
871 aInfo.
uuid =
KIID( wxString( aJson[
"uuid"].get<std::string>().c_str(), wxConvUTF8 ) );
873 if( aJson.contains(
"name" ) )
874 aInfo.
name = wxString( aJson[
"name"].get<std::string>().c_str(), wxConvUTF8 );
876 if( aJson.contains(
"filename" ) )
877 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.
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 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.