34#include <wx/filename.h>
102 [&]() -> nlohmann::json
104 nlohmann::json ret = nlohmann::json::array();
107 ret.push_back( libName );
111 [&](
const nlohmann::json& aJson )
113 if( aJson.empty() || !aJson.is_array() )
118 for(
const nlohmann::json& entry : aJson )
123 [&]() -> nlohmann::json
125 nlohmann::json ret = nlohmann::json::object();
129 nlohmann::json members = nlohmann::json::array();
131 for(
const wxString& member : alias.second )
132 members.push_back( member );
134 ret[ alias.first.ToStdString() ] = members;
139 [&](
const nlohmann::json& aJson )
141 if( aJson.empty() || !aJson.is_object() )
146 for(
auto it = aJson.begin(); it != aJson.end(); ++it )
148 const nlohmann::json& membersJson = it.value();
150 if( !membersJson.is_array() )
153 std::vector<wxString> members;
155 for(
const nlohmann::json& entry : membersJson )
157 if( entry.is_string() )
159 wxString member = entry.get<wxString>().Strip( wxString::both );
161 if( !member.IsEmpty() )
162 members.push_back( member );
166 wxString
name = wxString::FromUTF8( it.key().c_str() ).Strip( wxString::both );
168 if( !
name.IsEmpty() )
173 m_NetSettings = std::make_shared<NET_SETTINGS>(
this,
"net_settings" );
176 std::make_shared<COMPONENT_CLASS_SETTINGS>(
this,
"component_class_settings" );
217 auto p(
"/board/layer_presets"_json_pointer );
224 for( nlohmann::json& entry : presets )
235 auto p(
"/board/layer_presets"_json_pointer );
242 for( nlohmann::json& entry : presets )
257 std::set<wxString> group_blacklist;
264 auto loadPinnedLibs =
265 [&](
const std::string& aDest )
268 wxString libKey = wxT(
"PinnedItems" );
271 nlohmann::json libs = nlohmann::json::array();
273 while( aCfg->Read( libKey, &str ) )
275 libs.push_back( str );
277 aCfg->DeleteEntry( libKey,
true );
279 libKey = wxT(
"PinnedItems" );
280 libKey << ++libIndex;
286 aCfg->SetPath( wxT(
"/LibeditFrame" ) );
287 loadPinnedLibs(
"libraries.pinned_symbol_libs" );
289 aCfg->SetPath( wxT(
"/ModEditFrame" ) );
290 loadPinnedLibs(
"libraries.pinned_footprint_libs" );
292 aCfg->SetPath( wxT(
"/cvpcb/equfiles" ) );
296 wxString eqKey = wxT(
"EquName" );
299 nlohmann::json eqs = nlohmann::json::array();
301 while( aCfg->Read( eqKey, &str ) )
303 eqs.push_back( str );
305 eqKey = wxT(
"EquName" );
309 Set(
"cvpcb.equivalence_files", eqs );
313 group_blacklist.insert( wxT(
"/cvpcb" ) );
315 aCfg->SetPath( wxT(
"/eeschema" ) );
318 aCfg->SetPath( wxT(
"/eeschema/libraries" ) );
322 wxString libKey = wxT(
"LibName" );
325 nlohmann::json libs = nlohmann::json::array();
327 while( aCfg->Read( libKey, &str ) )
329 libs.push_back( str );
331 libKey = wxT(
"LibName" );
335 Set(
"schematic.legacy_lib_list", libs );
338 group_blacklist.insert( wxT(
"/eeschema" ) );
340 aCfg->SetPath( wxT(
"/text_variables" ) );
347 nlohmann::json vars = nlohmann::json();
349 while( aCfg->Read( txtKey, &str ) )
351 wxArrayString tokens = wxSplit( str,
':' );
353 if( tokens.size() == 2 )
354 vars[ tokens[0].ToStdString() ] = tokens[1];
360 Set(
"text_variables", vars );
363 group_blacklist.insert( wxT(
"/text_variables" ) );
365 aCfg->SetPath( wxT(
"/schematic_editor" ) );
367 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"schematic.page_layout_descr_file" );
370 fromLegacy<bool>( aCfg,
"SpiceAjustPassiveValues",
"schematic.spice_adjust_passive_values" );
371 fromLegacy<int>( aCfg,
"SubpartIdSeparator",
"schematic.subpart_id_separator" );
372 fromLegacy<int>( aCfg,
"SubpartFirstId",
"schematic.subpart_first_id" );
374 fromLegacy<int>( aCfg,
"LineThickness",
"schematic.drawing.default_line_thickness" );
375 fromLegacy<int>( aCfg,
"WireThickness",
"schematic.drawing.default_wire_thickness" );
376 fromLegacy<int>( aCfg,
"BusThickness",
"schematic.drawing.default_bus_thickness" );
377 fromLegacy<int>( aCfg,
"LabSize",
"schematic.drawing.default_text_size" );
379 if( !
fromLegacy<int>( aCfg,
"PinSymbolSize",
"schematic.drawing.pin_symbol_size" ) )
382 Set(
"schematic.drawing.pin_symbol_size", 0 );
385 fromLegacy<int>( aCfg,
"JunctionSize",
"schematic.drawing.default_junction_size" );
387 fromLegacyString( aCfg,
"FieldNameTemplates",
"schematic.drawing.field_names" );
389 if( !
fromLegacy<double>( aCfg,
"TextOffsetRatio",
"schematic.drawing.text_offset_ratio" ) )
392 Set(
"schematic.drawing.text_offset_ratio", 0.08 );
393 Set(
"schematic.drawing.label_size_ratio", 0.25 );
397 group_blacklist.insert( wxT(
"/schematic_editor" ) );
399 aCfg->SetPath( wxT(
"/pcbnew" ) );
401 fromLegacyString( aCfg,
"PageLayoutDescrFile",
"pcbnew.page_layout_descr_file" );
406 fromLegacyString( aCfg,
"LastSpecctraDSNExportPath",
"pcbnew.last_paths.specctra_dsn" );
407 fromLegacyString( aCfg,
"LastGenCADExportPath",
"pcbnew.last_paths.gencad" );
409 std::string bp =
"board.design_settings.";
413 wxString key = wxT(
"DRCExclusion" );
416 nlohmann::json exclusions = nlohmann::json::array();
418 while( aCfg->Read( key, &str ) )
420 exclusions.push_back( str );
422 key = wxT(
"DRCExclusion" );
426 Set( bp +
"drc_exclusions", exclusions );
430 fromLegacy<bool>( aCfg,
"AllowBlindVias", bp +
"rules.allow_blind_buried_vias" );
436 if( !
fromLegacy<double>( aCfg,
"MinThroughDrill", bp +
"rules.min_through_hole_diameter" ) )
439 fromLegacy<double>( aCfg,
"MinMicroViaDiameter", bp +
"rules.min_microvia_diameter" );
442 fromLegacy<double>( aCfg,
"CopperEdgeClearance", bp +
"rules.min_copper_edge_clearance" );
443 fromLegacy<double>( aCfg,
"SolderMaskClearance", bp +
"rules.solder_mask_clearance" );
445 fromLegacy<double>( aCfg,
"SolderPasteClearance", bp +
"rules.solder_paste_clearance" );
446 fromLegacy<double>( aCfg,
"SolderPasteRatio", bp +
"rules.solder_paste_margin_ratio" );
449 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.silk_line_width" );
457 if( !
fromLegacy<double>( aCfg,
"SilkTextSizeThickness", bp +
"defaults.silk_text_thickness" ) )
458 fromLegacy<double>( aCfg,
"ModuleTextSizeThickness", bp +
"defaults.silk_text_thickness" );
460 fromLegacy<bool>( aCfg,
"SilkTextItalic", bp +
"defaults.silk_text_italic" );
461 fromLegacy<bool>( aCfg,
"SilkTextUpright", bp +
"defaults.silk_text_upright" );
463 if( !
fromLegacy<double>( aCfg,
"CopperLineWidth", bp +
"defaults.copper_line_width" ) )
466 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeV", bp +
"defaults.copper_text_size_v" ) )
469 if( !
fromLegacy<double>( aCfg,
"CopperTextSizeH", bp +
"defaults.copper_text_size_h" ) )
472 if( !
fromLegacy<double>( aCfg,
"CopperTextThickness", bp +
"defaults.copper_text_thickness" ) )
473 fromLegacy<double>( aCfg,
"PcbTextThickness", bp +
"defaults.copper_text_thickness" );
475 fromLegacy<bool>( aCfg,
"CopperTextItalic", bp +
"defaults.copper_text_italic" );
476 fromLegacy<bool>( aCfg,
"CopperTextUpright", bp +
"defaults.copper_text_upright" );
478 if( !
fromLegacy<double>( aCfg,
"EdgeCutLineWidth", bp +
"defaults.board_outline_line_width" ) )
480 bp +
"defaults.board_outline_line_width" );
482 fromLegacy<double>( aCfg,
"CourtyardLineWidth", bp +
"defaults.courtyard_line_width" );
487 fromLegacy<double>( aCfg,
"FabTextSizeThickness", bp +
"defaults.fab_text_thickness" );
489 fromLegacy<bool>( aCfg,
"FabTextUpright", bp +
"defaults.fab_text_upright" );
491 if( !
fromLegacy<double>( aCfg,
"OthersLineWidth", bp +
"defaults.other_line_width" ) )
492 fromLegacy<double>( aCfg,
"ModuleOutlineThickness", bp +
"defaults.other_line_width" );
496 fromLegacy<double>( aCfg,
"OthersTextSizeThickness", bp +
"defaults.other_text_thickness" );
497 fromLegacy<bool>( aCfg,
"OthersTextItalic", bp +
"defaults.other_text_italic" );
498 fromLegacy<bool>( aCfg,
"OthersTextUpright", bp +
"defaults.other_text_upright" );
500 fromLegacy<int>( aCfg,
"DimensionUnits", bp +
"defaults.dimension_units" );
501 fromLegacy<int>( aCfg,
"DimensionPrecision", bp +
"defaults.dimension_precision" );
503 std::string sev = bp +
"rule_severities";
505 fromLegacy<bool>( aCfg,
"RequireCourtyardDefinitions", sev +
"legacy_no_courtyard_defined" );
507 fromLegacy<bool>( aCfg,
"ProhibitOverlappingCourtyards", sev +
"legacy_courtyards_overlap" );
511 wxString keyBase =
"TrackWidth";
512 wxString key = keyBase;
515 nlohmann::json widths = nlohmann::json::array();
519 while( aCfg->Read( key, &val ) )
521 widths.push_back( val );
526 Set( bp +
"track_widths", widths );
531 wxString keyBase =
"ViaDiameter";
532 wxString key = keyBase;
536 nlohmann::json vias = nlohmann::json::array();
540 while( aCfg->Read( key, &diameter ) )
543 aCfg->Read( key << idx, &drill );
545 nlohmann::json
via = { {
"diameter", diameter }, {
"drill", drill } };
546 vias.push_back(
via );
552 Set( bp +
"via_dimensions", vias );
557 wxString keyBase =
"dPairWidth";
558 wxString key = keyBase;
561 double via_gap = 1.0;
563 nlohmann::json pairs = nlohmann::json::array();
567 while( aCfg->Read( key, &width ) )
570 aCfg->Read( key << idx, &gap );
573 aCfg->Read( key << idx, &via_gap );
575 nlohmann::json pair = { {
"width", width }, {
"gap", gap }, {
"via_gap", via_gap } };
576 pairs.push_back( pair );
582 Set( bp +
"diff_pair_dimensions", pairs );
585 group_blacklist.insert( wxT(
"/pcbnew" ) );
588 group_blacklist.insert( wxT(
"/general" ) );
591 aCfg->SetPath( wxT(
"/" ) );
593 auto loadSheetNames =
598 nlohmann::json arr = nlohmann::json::array();
602 aCfg->SetPath( wxT(
"/sheetnames" ) );
604 while( aCfg->Read( wxString::Format(
"%d", sheet++ ), &entry ) )
606 wxArrayString tokens = wxSplit( entry,
':' );
608 if( tokens.size() == 2 )
610 wxLogTrace(
traceSettings, wxT(
"%d: %s = %s" ), sheet, tokens[0],
612 arr.push_back( nlohmann::json::array( { tokens[0], tokens[1] } ) );
616 Set(
"sheets", arr );
618 aCfg->SetPath(
"/" );
623 std::vector<wxString> groups;
625 groups.emplace_back( wxEmptyString );
627 auto loadLegacyPairs =
628 [&](
const std::string& aGroup ) ->
bool
630 wxLogTrace(
traceSettings, wxT(
"Migrating group %s" ), aGroup );
637 while( aCfg->GetNextEntry( keyStr,
index ) )
639 if( !aCfg->Read( keyStr, &val ) )
642 std::string key( keyStr.ToUTF8() );
648 Set(
"legacy." + aGroup +
"." + key, val );
659 for(
size_t i = 0; i < groups.size(); i++ )
661 aCfg->SetPath( groups[i] );
663 if( groups[i] == wxT(
"/sheetnames" ) )
665 ret |= loadSheetNames();
669 aCfg->DeleteEntry( wxT(
"last_client" ),
true );
670 aCfg->DeleteEntry( wxT(
"update" ),
true );
671 aCfg->DeleteEntry( wxT(
"version" ),
true );
673 ret &= loadLegacyPairs( groups[i].ToStdString() );
677 while( aCfg->GetNextGroup( str,
index ) )
679 wxString
group = groups[i] +
"/" + str;
681 if( !group_blacklist.count(
group ) )
682 groups.emplace_back(
group );
685 aCfg->SetPath(
"/" );
702 wxString projectName =
m_project->GetProjectName();
706 defaultSheet.
name = projectName;
707 defaultSheet.
filename = projectName +
".kicad_sch";
714 wxLogTrace(
traceSettings, wxT(
"PROJECT_FILE: Migrated old single-root format to top_level_sheets" ) );
723 wxString projectPath =
m_project->GetProjectPath();
724 wxString projectName =
m_project->GetProjectName();
728 wxFileName referencedFile( projectPath, sheetInfo.filename );
730 if( referencedFile.FileExists() )
734 wxString expectedFile =
737 wxFileName candidateFile( projectPath, expectedFile );
739 if( candidateFile.FileExists() )
742 wxT(
"PROJECT_FILE: Fixing stale top_level_sheets reference "
744 sheetInfo.filename, expectedFile );
746 sheetInfo.filename = expectedFile;
747 sheetInfo.name = projectName;
778 wxString oldProjectName = oldFilename.GetName();
779 wxString oldProjectPath = oldFilename.GetPath();
785 [&]( wxString& aPath )
787 if( aPath.StartsWith( oldProjectName + wxS(
"." ) ) )
788 aPath.Replace( oldProjectName, aFile,
false );
789 else if( aPath.StartsWith( oldProjectPath + wxS(
"/" ) ) )
790 aPath.Replace( oldProjectPath, aDirectory,
false );
798 auto updatePathByPtr =
799 [&](
const std::string& aPtr )
803 updatePath(
path.value() );
808 updatePathByPtr(
"schematic.page_layout_descr_file" );
809 updatePathByPtr(
"schematic.plot_directory" );
810 updatePathByPtr(
"schematic.ngspice.workbook_filename" );
811 updatePathByPtr(
"pcbnew.page_layout_descr_file" );
815 updatePath( sheetInfo.filename );
818 if( sheetInfo.name == oldProjectName )
819 sheetInfo.name = aFile;
847 aJson = nlohmann::json::array( { aPair.first.AsString().ToUTF8(), aPair.second.ToUTF8() } );
853 wxCHECK( aJson.is_array() && aJson.size() == 2, );
854 aPair.first =
KIID( wxString( aJson[0].get<std::string>().c_str(), wxConvUTF8 ) );
855 aPair.second = wxString( aJson[1].get<std::string>().c_str(), wxConvUTF8 );
861 aJson = nlohmann::json::object();
863 aJson[
"name"] = aInfo.
name.ToUTF8();
864 aJson[
"filename"] = aInfo.
filename.ToUTF8();
870 wxCHECK( aJson.is_object(), );
872 if( aJson.contains(
"uuid" ) )
873 aInfo.
uuid =
KIID( wxString( aJson[
"uuid"].get<std::string>().c_str(), wxConvUTF8 ) );
875 if( aJson.contains(
"name" ) )
876 aInfo.
name = wxString( aJson[
"name"].get<std::string>().c_str(), wxConvUTF8 );
878 if( aJson.contains(
"filename" ) )
879 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.