Rework JSON integration to speed up build

This commit is contained in:
Jon Evans 2021-06-03 23:52:50 -04:00
parent 42394b16a3
commit c9a660a80c
28 changed files with 680 additions and 439 deletions

View File

@ -240,7 +240,7 @@ bool EDA_3D_VIEWER_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
if( aCfg->Read( k_r, &color.r ) && if( aCfg->Read( k_r, &color.r ) &&
aCfg->Read( k_g, &color.g ) && aCfg->Read( k_b, &color.b ) ) aCfg->Read( k_g, &color.g ) && aCfg->Read( k_b, &color.b ) )
{ {
( *this )[PointerFromString( destKey )] = color; Set( destKey, color );
} }
}; };

View File

@ -457,6 +457,7 @@ set( COMMON_SRCS
settings/common_settings.cpp settings/common_settings.cpp
settings/json_settings.cpp settings/json_settings.cpp
settings/nested_settings.cpp settings/nested_settings.cpp
settings/parameters.cpp
settings/settings_manager.cpp settings/settings_manager.cpp
project/board_project_settings.cpp project/board_project_settings.cpp

View File

@ -18,6 +18,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <nlohmann/json.hpp>
#include <project/net_settings.h> #include <project/net_settings.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>

View File

@ -21,6 +21,7 @@
#include <config_params.h> #include <config_params.h>
#include <project.h> #include <project.h>
#include <project/net_settings.h> #include <project/net_settings.h>
#include <settings/json_settings_internals.h>
#include <project/project_file.h> #include <project/project_file.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/parameters.h> #include <settings/parameters.h>
@ -142,7 +143,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
libKey << ++libIndex; libKey << ++libIndex;
} }
( *this )[PointerFromString( aDest )] = libs; Set( aDest, libs );
}; };
aCfg->SetPath( wxT( "/LibeditFrame" ) ); aCfg->SetPath( wxT( "/LibeditFrame" ) );
@ -168,7 +169,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
eqKey << ++eqIdx; eqKey << ++eqIdx;
} }
( *this )[PointerFromString( "cvpcb.equivalence_files" )] = eqs; Set( "cvpcb.equivalence_files", eqs );
} }
// All CvPcb params that we want to keep have been migrated above // All CvPcb params that we want to keep have been migrated above
@ -194,7 +195,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
libKey << ++libIdx; libKey << ++libIdx;
} }
( *this )[PointerFromString( "schematic.legacy_lib_list" )] = libs; Set( "schematic.legacy_lib_list", libs );
} }
group_blacklist.insert( wxT( "/eeschema" ) ); group_blacklist.insert( wxT( "/eeschema" ) );
@ -219,7 +220,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
txtKey << ++txtIdx; txtKey << ++txtIdx;
} }
( *this )[PointerFromString( "text_variables" )] = vars; Set( "text_variables", vars );
} }
group_blacklist.insert( wxT( "/text_variables" ) ); group_blacklist.insert( wxT( "/text_variables" ) );
@ -273,7 +274,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
key << ++idx; key << ++idx;
} }
( *this )[PointerFromString( bp + "drc_exclusions" )] = exclusions; Set( bp + "drc_exclusions", exclusions );
} }
fromLegacy<bool>( aCfg, "AllowMicroVias", bp + "rules.allow_microvias" ); fromLegacy<bool>( aCfg, "AllowMicroVias", bp + "rules.allow_microvias" );
@ -372,7 +373,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
key << ++idx; key << ++idx;
} }
( *this )[PointerFromString( bp + "track_widths" )] = widths; Set( bp + "track_widths", widths );
} }
{ {
@ -398,7 +399,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
key << ++idx; key << ++idx;
} }
( *this )[PointerFromString( bp + "via_dimensions" )] = vias; Set( bp + "via_dimensions", vias );
} }
{ {
@ -428,7 +429,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
key << ++idx; key << ++idx;
} }
( *this )[PointerFromString( bp + "diff_pair_dimensions" )] = pairs; Set( bp + "diff_pair_dimensions", pairs );
} }
group_blacklist.insert( wxT( "/pcbnew" ) ); group_blacklist.insert( wxT( "/pcbnew" ) );
@ -461,7 +462,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
} }
} }
( *this )[PointerFromString( "sheets" )] = arr; Set( "sheets", arr );
aCfg->SetPath( "/" ); aCfg->SetPath( "/" );
@ -494,8 +495,7 @@ bool PROJECT_FILE::MigrateFromLegacy( wxConfigBase* aCfg )
try try
{ {
nlohmann::json::json_pointer ptr( "/legacy" + aGroup + "/" + key ); Set( "legacy." + aGroup + "." + key, val );
( *this )[ptr] = val;
} }
catch( ... ) catch( ... )
{ {
@ -543,8 +543,7 @@ bool PROJECT_FILE::SaveToFile( const wxString& aDirectory, bool aForce )
{ {
wxASSERT( m_project ); wxASSERT( m_project );
( *this )[PointerFromString( "meta.filename" )] = Set( "meta.filename", m_project->GetProjectName() + "." + ProjectFileExtension );
m_project->GetProjectName() + "." + ProjectFileExtension;
return JSON_SETTINGS::SaveToFile( aDirectory, aForce ); return JSON_SETTINGS::SaveToFile( aDirectory, aForce );
} }

View File

@ -20,6 +20,7 @@
#include <project.h> #include <project.h>
#include <project/project_local_settings.h> #include <project/project_local_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>
const int projectLocalSettingsVersion = 3; const int projectLocalSettingsVersion = 3;
@ -230,18 +231,18 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
* LAYER_PADS and LAYER_ZONES added to visibility controls * LAYER_PADS and LAYER_ZONES added to visibility controls
*/ */
nlohmann::json::json_pointer ptr( "/board/visible_items"_json_pointer ); std::string ptr( "board.visible_items" );
if( contains( ptr ) ) if( Contains( ptr ) )
{ {
if( ( *this )[ptr].is_array() ) if( At( ptr ).is_array() )
{ {
( *this )[ptr].push_back( LAYER_PADS ); At( ptr ).push_back( LAYER_PADS );
( *this )[ptr].push_back( LAYER_ZONES ); At( ptr ).push_back( LAYER_ZONES );
} }
else else
{ {
at( "board" ).erase( "visible_items" ); At( "board" ).erase( "visible_items" );
} }
} }
@ -277,13 +278,13 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
{ 40, 33 }, // LAYER_ZONES { 40, 33 }, // LAYER_ZONES
}; };
nlohmann::json::json_pointer ptr( "/board/visible_items"_json_pointer ); std::string ptr( "board.visible_items" );
if( contains( ptr ) && at( ptr ).is_array() ) if( Contains( ptr ) && At( ptr ).is_array() )
{ {
nlohmann::json visible = nlohmann::json::array(); nlohmann::json visible = nlohmann::json::array();
for( const nlohmann::json& val : at( ptr ) ) for( const nlohmann::json& val : At( ptr ) )
{ {
try try
{ {
@ -300,7 +301,7 @@ PROJECT_LOCAL_SETTINGS::PROJECT_LOCAL_SETTINGS( PROJECT* aProject, const wxStrin
} }
} }
at( "board" )["visible_items"] = visible; At( "board" )["visible_items"] = visible;
} }
return true; return true;
@ -323,8 +324,7 @@ bool PROJECT_LOCAL_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce
{ {
wxASSERT( m_project ); wxASSERT( m_project );
( *this )[PointerFromString( "meta.filename" )] = Set( "meta.filename", m_project->GetProjectName() + "." + ProjectLocalSettingsFileExtension );
m_project->GetProjectName() + "." + ProjectLocalSettingsFileExtension;
return JSON_SETTINGS::SaveToFile( aDirectory, aForce ); return JSON_SETTINGS::SaveToFile( aDirectory, aForce );
} }

View File

@ -23,6 +23,7 @@
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <settings/app_settings.h> #include <settings/app_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <base_units.h> #include <base_units.h>
@ -175,7 +176,7 @@ bool APP_SETTINGS_BASE::MigrateFromLegacy( wxConfigBase* aCfg )
js.push_back( i ); js.push_back( i );
} }
( *this )[PointerFromString( "printing.layers" ) ] = js; Set( "printing.layers", js );
} }
ret &= fromLegacy<bool>( aCfg, f + "FirstRunShown", "system.first_run_shown" ); ret &= fromLegacy<bool>( aCfg, f + "FirstRunShown", "system.first_run_shown" );
@ -196,7 +197,7 @@ bool APP_SETTINGS_BASE::MigrateFromLegacy( wxConfigBase* aCfg )
js.push_back( file.ToStdString() ); js.push_back( file.ToStdString() );
} }
( *this )[PointerFromString( "system.file_history" )] = js; Set( "system.file_history", js );
} }
ret &= migrateWindowConfig( aCfg, f, "window" ); ret &= migrateWindowConfig( aCfg, f, "window" );
@ -224,8 +225,8 @@ void APP_SETTINGS_BASE::migrateFindReplace( wxConfigBase* aCfg )
replace_history.push_back( tmp.ToStdString() ); replace_history.push_back( tmp.ToStdString() );
} }
( *this )[PointerFromString( "find_replace.find_history" )] = find_history; Set( "find_replace.find_history", find_history );
( *this )[PointerFromString( "find_replace.replace_history" )] = replace_history; Set( "find_replace.replace_history", replace_history );
} }

View File

@ -21,6 +21,7 @@
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <settings/color_settings.h> #include <settings/color_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <wx/log.h> #include <wx/log.h>
@ -223,7 +224,7 @@ COLOR_SETTINGS::COLOR_SETTINGS( wxString aFilename ) :
// Fix LAYER_VIA_HOLES color - before version 2, this setting had no effect // Fix LAYER_VIA_HOLES color - before version 2, this setting had no effect
nlohmann::json::json_pointer ptr( "/board/via_hole"); nlohmann::json::json_pointer ptr( "/board/via_hole");
( *this )[ptr] = COLOR4D( 0.5, 0.4, 0, 0.8 ).ToWxString( wxC2S_CSS_SYNTAX ); ( *m_internals )[ptr] = COLOR4D( 0.5, 0.4, 0, 0.8 ).ToWxString( wxC2S_CSS_SYNTAX );
return true; return true;
} ); } );
@ -285,10 +286,7 @@ bool COLOR_SETTINGS::migrateSchema0to1()
return false; return false;
} }
nlohmann::json::json_pointer board( "/board" ); if( !Contains( "fpedit" ) )
nlohmann::json::json_pointer fpedit( "/fpedit" );
if( !contains( fpedit ) )
{ {
wxLogTrace( traceSettings, "migrateSchema0to1: %s doesn't have fpedit settings; skipping.", wxLogTrace( traceSettings, "migrateSchema0to1: %s doesn't have fpedit settings; skipping.",
m_filename ); m_filename );
@ -300,19 +298,18 @@ bool COLOR_SETTINGS::migrateSchema0to1()
COLOR_SETTINGS* fpsettings = m_manager->AddNewColorSettings( filename ); COLOR_SETTINGS* fpsettings = m_manager->AddNewColorSettings( filename );
// Start out with a clone // Start out with a clone
nlohmann::json::json_pointer root( "" ); fpsettings->Set( "", At( "" ) );
( *fpsettings )[root] = at( root );
// Footprint editor now just looks at the "board" namespace // Footprint editor now just looks at the "board" namespace
( *fpsettings )[board] = fpsettings->at( fpedit ); fpsettings->Set( "board", fpsettings->At( "fpedit" ) );
fpsettings->erase( "fpedit" ); fpsettings->Internals()->erase( "fpedit" );
fpsettings->Load(); fpsettings->Load();
fpsettings->SetName( fpsettings->GetName() + wxS( " " ) + _( "(Footprints)" ) ); fpsettings->SetName( fpsettings->GetName() + wxS( " " ) + _( "(Footprints)" ) );
m_manager->Save( fpsettings ); m_manager->Save( fpsettings );
// Now we can get rid of our own copy // Now we can get rid of our own copy
erase( "fpedit" ); m_internals->erase( "fpedit" );
return true; return true;
} }

View File

@ -23,6 +23,7 @@
#include <paths.h> #include <paths.h>
#include <search_stack.h> #include <search_stack.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <systemdirsappend.h> #include <systemdirsappend.h>
#include <trace_helpers.h> #include <trace_helpers.h>
@ -300,8 +301,8 @@ bool COMMON_SETTINGS::migrateSchema0to1()
try try
{ {
mwp = at( mwp_pointer ); mwp = m_internals->at( mwp_pointer );
at( nlohmann::json::json_pointer( "/input"_json_pointer ) ).erase( "mousewheel_pan" ); m_internals->At( "input" ).erase( "mousewheel_pan" );
} }
catch( ... ) catch( ... )
{ {
@ -310,19 +311,19 @@ bool COMMON_SETTINGS::migrateSchema0to1()
if( mwp ) if( mwp )
{ {
( *this )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = true; ( *m_internals )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = true;
( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_SHIFT; ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_SHIFT;
( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = 0; ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = 0;
( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = WXK_CONTROL; ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = WXK_CONTROL;
} }
else else
{ {
( *this )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = false; ( *m_internals )[nlohmann::json::json_pointer( "/input/horizontal_pan" )] = false;
( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_CONTROL; ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_h" )] = WXK_CONTROL;
( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = WXK_SHIFT; ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_pan_v" )] = WXK_SHIFT;
( *this )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = 0; ( *m_internals )[nlohmann::json::json_pointer( "/input/scroll_modifier_zoom" )] = 0;
} }
return true; return true;
@ -337,8 +338,8 @@ bool COMMON_SETTINGS::migrateSchema1to2()
try try
{ {
prefer_selection = at( v1_pointer ); prefer_selection = m_internals->at( v1_pointer );
at( nlohmann::json::json_pointer( "/input"_json_pointer ) ).erase( "prefer_select_to_drag" ); m_internals->at( nlohmann::json::json_pointer( "/input"_json_pointer ) ).erase( "prefer_select_to_drag" );
} }
catch( ... ) catch( ... )
{ {
@ -346,9 +347,9 @@ bool COMMON_SETTINGS::migrateSchema1to2()
} }
if( prefer_selection ) if( prefer_selection )
( *this )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::SELECT; ( *m_internals )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::SELECT;
else else
( *this )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::DRAG_ANY; ( *m_internals )[nlohmann::json::json_pointer( "/input/mouse_left" )] = MOUSE_DRAG_ACTION::DRAG_ANY;
return true; return true;
} }
@ -374,10 +375,10 @@ bool COMMON_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
auto load_env_vars = [&] () { auto load_env_vars = [&] () {
wxString key, value; wxString key, value;
long index = 0; long index = 0;
nlohmann::json::json_pointer ptr = PointerFromString( "environment.vars" ); nlohmann::json::json_pointer ptr = m_internals->PointerFromString( "environment.vars" );
aCfg->SetPath( "EnvironmentVariables" ); aCfg->SetPath( "EnvironmentVariables" );
( *this )[ptr] = nlohmann::json( {} ); ( *m_internals )[ptr] = nlohmann::json( {} );
while( aCfg->GetNextEntry( key, index ) ) while( aCfg->GetNextEntry( key, index ) )
{ {
@ -394,7 +395,7 @@ bool COMMON_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
ptr.push_back( key.ToStdString() ); ptr.push_back( key.ToStdString() );
wxLogTrace( traceSettings, "Migrate Env: %s=%s", ptr.to_string(), value ); wxLogTrace( traceSettings, "Migrate Env: %s=%s", ptr.to_string(), value );
( *this )[ptr] = value.ToUTF8(); ( *m_internals )[ptr] = value.ToUTF8();
ptr.pop_back(); ptr.pop_back();
} }
@ -409,11 +410,10 @@ bool COMMON_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
if( aCfg->Read( "MousewheelPAN", &mousewheel_pan ) && mousewheel_pan ) if( aCfg->Read( "MousewheelPAN", &mousewheel_pan ) && mousewheel_pan )
{ {
( *this )[PointerFromString( "input.horizontal_pan" )] = true; Set( "input.horizontal_pan", true );
Set( "input.scroll_modifier_pan_h", static_cast<int>( WXK_SHIFT ) );
( *this )[PointerFromString( "input.scroll_modifier_pan_h" )] = WXK_SHIFT; Set( "input.scroll_modifier_pan_v", 0 );
( *this )[PointerFromString( "input.scroll_modifier_pan_v" )] = 0; Set( "input.scroll_modifier_zoom", static_cast<int>( WXK_CONTROL ) );
( *this )[PointerFromString( "input.scroll_modifier_zoom" )] = WXK_CONTROL;
} }
ret &= fromLegacy<bool>( aCfg, "AutoPAN", "input.auto_pan" ); ret &= fromLegacy<bool>( aCfg, "AutoPAN", "input.auto_pan" );
@ -423,11 +423,8 @@ bool COMMON_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
ret &= fromLegacy<bool>( aCfg, "ZoomNoCenter", "input.center_on_zoom" ); ret &= fromLegacy<bool>( aCfg, "ZoomNoCenter", "input.center_on_zoom" );
// This was stored inverted in legacy config // This was stored inverted in legacy config
if( ret ) if( OPT<bool> value = Get<bool>( "input.center_on_zoom" ) )
{ Set( "input.center_on_zoom", !( *value ) );
auto p = PointerFromString( "input.center_on_zoom" );
( *this )[p] = !( *this )[p];
}
ret &= fromLegacy<int>( aCfg, "OpenGLAntialiasingMode", "graphics.opengl_antialiasing_mode" ); ret &= fromLegacy<int>( aCfg, "OpenGLAntialiasingMode", "graphics.opengl_antialiasing_mode" );
ret &= fromLegacy<int>( aCfg, "CairoAntialiasingMode", "graphics.cairo_antialiasing_mode" ); ret &= fromLegacy<int>( aCfg, "CairoAntialiasingMode", "graphics.cairo_antialiasing_mode" );

View File

@ -27,6 +27,7 @@
#include <locale_io.h> #include <locale_io.h>
#include <gal/color4d.h> #include <gal/color4d.h>
#include <settings/json_settings.h> #include <settings/json_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/nested_settings.h> #include <settings/nested_settings.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <wx/config.h> #include <wx/config.h>
@ -36,13 +37,32 @@
#include <wx/log.h> #include <wx/log.h>
#include <wx/wfstream.h> #include <wx/wfstream.h>
const wxChar* const traceSettings = wxT( "KICAD_SETTINGS" ); const wxChar* const traceSettings = wxT( "KICAD_SETTINGS" );
nlohmann::json::json_pointer JSON_SETTINGS_INTERNALS::PointerFromString( std::string aPath )
{
std::replace( aPath.begin(), aPath.end(), '.', '/' );
aPath.insert( 0, "/" );
nlohmann::json::json_pointer p;
try
{
p = nlohmann::json::json_pointer( aPath );
}
catch( ... )
{
wxASSERT_MSG( false, wxT( "Invalid pointer path in PointerFromString!" ) );
}
return p;
}
JSON_SETTINGS::JSON_SETTINGS( const wxString& aFilename, SETTINGS_LOC aLocation, JSON_SETTINGS::JSON_SETTINGS( const wxString& aFilename, SETTINGS_LOC aLocation,
int aSchemaVersion, bool aCreateIfMissing, bool aCreateIfDefault, int aSchemaVersion, bool aCreateIfMissing, bool aCreateIfDefault,
bool aWriteFile ) : bool aWriteFile ) :
nlohmann::json(),
m_filename( aFilename ), m_filename( aFilename ),
m_legacy_filename( "" ), m_legacy_filename( "" ),
m_location( aLocation ), m_location( aLocation ),
@ -54,9 +74,11 @@ JSON_SETTINGS::JSON_SETTINGS( const wxString& aFilename, SETTINGS_LOC aLocation,
m_schemaVersion( aSchemaVersion ), m_schemaVersion( aSchemaVersion ),
m_manager( nullptr ) m_manager( nullptr )
{ {
m_internals = std::make_unique<JSON_SETTINGS_INTERNALS>();
try try
{ {
( *this )[PointerFromString( "meta.filename" )] = GetFullFilename(); m_internals->SetFromString( "meta.filename", GetFullFilename() );
} }
catch( ... ) catch( ... )
{ {
@ -85,6 +107,30 @@ wxString JSON_SETTINGS::GetFullFilename() const
} }
nlohmann::json& JSON_SETTINGS::At( const std::string& aPath )
{
return m_internals->At( aPath );
}
bool JSON_SETTINGS::Contains( const std::string& aPath ) const
{
return m_internals->contains( JSON_SETTINGS_INTERNALS::PointerFromString( aPath ) );
}
size_t JSON_SETTINGS::Count( const std::string& aPath ) const
{
return m_internals->count( JSON_SETTINGS_INTERNALS::PointerFromString( aPath ) );
}
JSON_SETTINGS_INTERNALS* JSON_SETTINGS::Internals()
{
return m_internals.get();
}
void JSON_SETTINGS::Load() void JSON_SETTINGS::Load()
{ {
for( auto param : m_params ) for( auto param : m_params )
@ -105,7 +151,7 @@ void JSON_SETTINGS::Load()
bool JSON_SETTINGS::LoadFromFile( const wxString& aDirectory ) bool JSON_SETTINGS::LoadFromFile( const wxString& aDirectory )
{ {
// First, load all params to default values // First, load all params to default values
clear(); m_internals->clear();
Load(); Load();
bool success = true; bool success = true;
@ -220,16 +266,17 @@ bool JSON_SETTINGS::LoadFromFile( const wxString& aDirectory )
if( fp ) if( fp )
{ {
*static_cast<nlohmann::json*>( this ) = nlohmann::json::parse( fp, nullptr, *static_cast<nlohmann::json*>( m_internals.get() ) =
/* allow_exceptions = */ true, nlohmann::json::parse( fp, nullptr,
/* ignore_comments = */ true ); /* allow_exceptions = */ true,
/* ignore_comments = */ true );
// If parse succeeds, check if schema migration is required // If parse succeeds, check if schema migration is required
int filever = -1; int filever = -1;
try try
{ {
filever = at( PointerFromString( "meta.version" ) ).get<int>(); filever = m_internals->Get<int>( "meta.version" );
} }
catch( ... ) catch( ... )
{ {
@ -407,7 +454,7 @@ bool JSON_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce )
try try
{ {
std::stringstream buffer; std::stringstream buffer;
buffer << std::setw( 2 ) << *this << std::endl; buffer << std::setw( 2 ) << *m_internals << std::endl;
wxFFileOutputStream fileStream( path.GetFullPath(), "wb" ); wxFFileOutputStream fileStream( path.GetFullPath(), "wb" );
@ -436,13 +483,13 @@ bool JSON_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce )
OPT<nlohmann::json> JSON_SETTINGS::GetJson( const std::string& aPath ) const OPT<nlohmann::json> JSON_SETTINGS::GetJson( const std::string& aPath ) const
{ {
nlohmann::json::json_pointer ptr = PointerFromString( aPath ); nlohmann::json::json_pointer ptr = m_internals->PointerFromString( aPath );
if( contains( ptr ) ) if( m_internals->contains( ptr ) )
{ {
try try
{ {
return OPT<nlohmann::json>{ at( ptr ) }; return OPT<nlohmann::json>{ m_internals->at( ptr ) };
} }
catch( ... ) catch( ... )
{ {
@ -453,6 +500,55 @@ OPT<nlohmann::json> JSON_SETTINGS::GetJson( const std::string& aPath ) const
} }
template<typename ValueType>
OPT<ValueType> JSON_SETTINGS::Get( const std::string& aPath ) const
{
if( OPT<nlohmann::json> ret = GetJson( aPath ) )
{
try
{
return ret->get<ValueType>();
}
catch( ... )
{
}
}
return NULLOPT;
}
// Instantiate all required templates here to allow reducing scope of json.hpp
template OPT<bool> JSON_SETTINGS::Get<bool>( const std::string& aPath ) const;
template OPT<double> JSON_SETTINGS::Get<double>( const std::string& aPath ) const;
template OPT<float> JSON_SETTINGS::Get<float>( const std::string& aPath ) const;
template OPT<unsigned int> JSON_SETTINGS::Get<unsigned int>( const std::string& aPath ) const;
template OPT<unsigned long long> JSON_SETTINGS::Get<unsigned long long>( const std::string& aPath ) const;
template OPT<std::string> JSON_SETTINGS::Get<std::string>( const std::string& aPath ) const;
template OPT<nlohmann::json> JSON_SETTINGS::Get<nlohmann::json>( const std::string& aPath ) const;
template OPT<KIGFX::COLOR4D> JSON_SETTINGS::Get<KIGFX::COLOR4D>( const std::string& aPath ) const;
template<typename ValueType>
void JSON_SETTINGS::Set( const std::string& aPath, ValueType aVal )
{
m_internals->SetFromString( aPath, aVal );
}
// Instantiate all required templates here to allow reducing scope of json.hpp
template void JSON_SETTINGS::Set<bool>( const std::string& aPath, bool aValue );
template void JSON_SETTINGS::Set<double>( const std::string& aPath, double aValue );
template void JSON_SETTINGS::Set<float>( const std::string& aPath, float aValue );
template void JSON_SETTINGS::Set<int>( const std::string& aPath, int aValue );
template void JSON_SETTINGS::Set<unsigned int>( const std::string& aPath, unsigned int aValue );
template void JSON_SETTINGS::Set<unsigned long long>( const std::string& aPath, unsigned long long aValue );
template void JSON_SETTINGS::Set<const char*>( const std::string& aPath, const char* aValue );
template void JSON_SETTINGS::Set<std::string>( const std::string& aPath, std::string aValue );
template void JSON_SETTINGS::Set<nlohmann::json>( const std::string& aPath, nlohmann::json aValue );
template void JSON_SETTINGS::Set<KIGFX::COLOR4D>( const std::string& aPath, KIGFX::COLOR4D aValue );
void JSON_SETTINGS::registerMigration( int aOldSchemaVersion, int aNewSchemaVersion, void JSON_SETTINGS::registerMigration( int aOldSchemaVersion, int aNewSchemaVersion,
std::function<bool()> aMigrator ) std::function<bool()> aMigrator )
{ {
@ -464,7 +560,7 @@ void JSON_SETTINGS::registerMigration( int aOldSchemaVersion, int aNewSchemaVers
bool JSON_SETTINGS::Migrate() bool JSON_SETTINGS::Migrate()
{ {
int filever = at( PointerFromString( "meta.version" ) ).get<int>(); int filever = m_internals->Get<int>( "meta.version" );
while( filever < m_schemaVersion ) while( filever < m_schemaVersion )
{ {
@ -482,7 +578,7 @@ bool JSON_SETTINGS::Migrate()
wxLogTrace( traceSettings, "Migrated %s from %d to %d", typeid( *this ).name(), wxLogTrace( traceSettings, "Migrated %s from %d to %d", typeid( *this ).name(),
filever, pair.first ); filever, pair.first );
filever = pair.first; filever = pair.first;
( *this )[PointerFromString( "meta.version" )] = filever; m_internals->At( "meta.version" ) = filever;
} }
else else
{ {
@ -504,30 +600,10 @@ bool JSON_SETTINGS::MigrateFromLegacy( wxConfigBase* aLegacyConfig )
} }
nlohmann::json::json_pointer JSON_SETTINGS::PointerFromString( std::string aPath )
{
std::replace( aPath.begin(), aPath.end(), '.', '/' );
aPath.insert( 0, "/" );
nlohmann::json::json_pointer p;
try
{
p = nlohmann::json::json_pointer( aPath );
}
catch( ... )
{
wxASSERT_MSG( false, wxT( "Invalid pointer path in PointerFromString!" ) );
}
return p;
}
bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath,
wxString& aTarget ) wxString& aTarget )
{ {
nlohmann::json::json_pointer ptr = PointerFromString( aPath ); nlohmann::json::json_pointer ptr = JSON_SETTINGS_INTERNALS::PointerFromString( aPath );
if( aObj.contains( ptr ) && aObj.at( ptr ).is_string() ) if( aObj.contains( ptr ) && aObj.at( ptr ).is_string() )
{ {
@ -542,7 +618,7 @@ bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string&
bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath,
bool& aTarget ) bool& aTarget )
{ {
nlohmann::json::json_pointer ptr = PointerFromString( aPath ); nlohmann::json::json_pointer ptr = JSON_SETTINGS_INTERNALS::PointerFromString( aPath );
if( aObj.contains( ptr ) && aObj.at( ptr ).is_boolean() ) if( aObj.contains( ptr ) && aObj.at( ptr ).is_boolean() )
{ {
@ -557,7 +633,7 @@ bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string&
bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath,
int& aTarget ) int& aTarget )
{ {
nlohmann::json::json_pointer ptr = PointerFromString( aPath ); nlohmann::json::json_pointer ptr = JSON_SETTINGS_INTERNALS::PointerFromString( aPath );
if( aObj.contains( ptr ) && aObj.at( ptr ).is_number_integer() ) if( aObj.contains( ptr ) && aObj.at( ptr ).is_number_integer() )
{ {
@ -572,7 +648,7 @@ bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string&
bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath, bool JSON_SETTINGS::SetIfPresent( const nlohmann::json& aObj, const std::string& aPath,
unsigned int& aTarget ) unsigned int& aTarget )
{ {
nlohmann::json::json_pointer ptr = PointerFromString( aPath ); nlohmann::json::json_pointer ptr = JSON_SETTINGS_INTERNALS::PointerFromString( aPath );
if( aObj.contains( ptr ) && aObj.at( ptr ).is_number_unsigned() ) if( aObj.contains( ptr ) && aObj.at( ptr ).is_number_unsigned() )
{ {
@ -594,7 +670,7 @@ bool JSON_SETTINGS::fromLegacy( wxConfigBase* aConfig, const std::string& aKey,
{ {
try try
{ {
( *this )[PointerFromString( aDest )] = val; ( *m_internals )[aDest] = val;
} }
catch( ... ) catch( ... )
{ {
@ -630,7 +706,7 @@ bool JSON_SETTINGS::fromLegacyString( wxConfigBase* aConfig, const std::string&
{ {
try try
{ {
( *this )[PointerFromString( aDest )] = str.ToUTF8(); ( *m_internals )[aDest] = str.ToUTF8();
} }
catch( ... ) catch( ... )
{ {
@ -658,7 +734,7 @@ bool JSON_SETTINGS::fromLegacyColor( wxConfigBase* aConfig, const std::string& a
try try
{ {
nlohmann::json js = nlohmann::json::array( { color.r, color.g, color.b, color.a } ); nlohmann::json js = nlohmann::json::array( { color.r, color.g, color.b, color.a } );
( *this )[PointerFromString( aDest )] = js; ( *m_internals )[aDest] = js;
} }
catch( ... ) catch( ... )
{ {
@ -714,7 +790,7 @@ template<> OPT<wxString> JSON_SETTINGS::Get( const std::string& aPath ) const
template<> void JSON_SETTINGS::Set<wxString>( const std::string& aPath, wxString aVal ) template<> void JSON_SETTINGS::Set<wxString>( const std::string& aPath, wxString aVal )
{ {
( *this )[PointerFromString( std::move( aPath ) ) ] = aVal.ToUTF8(); ( *m_internals )[aPath] = aVal.ToUTF8();
} }
// Specializations to allow directly reading/writing wxStrings from JSON // Specializations to allow directly reading/writing wxStrings from JSON

View File

@ -20,6 +20,7 @@
#include <wx/log.h> #include <wx/log.h>
#include <settings/json_settings_internals.h>
#include <settings/nested_settings.h> #include <settings/nested_settings.h>
NESTED_SETTINGS::NESTED_SETTINGS( const std::string& aName, int aVersion, JSON_SETTINGS* aParent, NESTED_SETTINGS::NESTED_SETTINGS( const std::string& aName, int aVersion, JSON_SETTINGS* aParent,
@ -40,18 +41,18 @@ NESTED_SETTINGS::~NESTED_SETTINGS()
bool NESTED_SETTINGS::LoadFromFile( const wxString& aDirectory ) bool NESTED_SETTINGS::LoadFromFile( const wxString& aDirectory )
{ {
clear(); m_internals->clear();
bool success = false; bool success = false;
if( m_parent ) if( m_parent )
{ {
nlohmann::json::json_pointer ptr = PointerFromString( m_path ); nlohmann::json::json_pointer ptr = m_internals->PointerFromString( m_path );
if( m_parent->contains( ptr ) ) if( m_parent->m_internals->contains( ptr ) )
{ {
try try
{ {
update( ( *m_parent )[ptr] ); m_internals->update( ( *m_parent->m_internals )[ptr] );
wxLogTrace( traceSettings, "Loaded NESTED_SETTINGS %s", GetFilename() ); wxLogTrace( traceSettings, "Loaded NESTED_SETTINGS %s", GetFilename() );
@ -71,7 +72,7 @@ bool NESTED_SETTINGS::LoadFromFile( const wxString& aDirectory )
try try
{ {
filever = at( PointerFromString( "meta.version" ) ).get<int>(); filever = m_internals->Get<int>( "meta.version" );
} }
catch( ... ) catch( ... )
{ {
@ -118,8 +119,9 @@ bool NESTED_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce )
try try
{ {
nlohmann::json patch = nlohmann::json patch = nlohmann::json::diff( *m_internals,
nlohmann::json::diff( *this, ( *m_parent )[PointerFromString( m_path )] ); m_parent->m_internals->Get<nlohmann::json>( m_path ) );
modified |= !patch.empty(); modified |= !patch.empty();
} }
catch( ... ) catch( ... )
@ -132,7 +134,7 @@ bool NESTED_SETTINGS::SaveToFile( const wxString& aDirectory, bool aForce )
try try
{ {
( *m_parent )[PointerFromString( m_path ) ].update( *this ); m_parent->m_internals->At( m_path ).update( *m_internals );
wxLogTrace( traceSettings, "Stored NESTED_SETTINGS %s with schema %d", wxLogTrace( traceSettings, "Stored NESTED_SETTINGS %s with schema %d",
GetFilename(), m_schemaVersion ); GetFilename(), m_schemaVersion );

View File

@ -0,0 +1,290 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 Jon Evans <jon@craftyjon.com>
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <wx/string.h>
#include <nlohmann/json.hpp>
#include <gal/color4d.h>
#include <project/project_file.h>
#include <settings/parameters.h>
template <typename ValueType>
void PARAM_LAMBDA<ValueType>::Load( JSON_SETTINGS* aSettings, bool aResetIfMissing ) const
{
if( m_readOnly )
return;
if( std::is_same<ValueType, nlohmann::json>::value )
{
if( OPT<nlohmann::json> optval = aSettings->GetJson( m_path ) )
m_setter( *optval );
else
m_setter( m_default );
}
else
{
if( OPT<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
m_setter( *optval );
else
m_setter( m_default );
}
}
template <typename ValueType>
bool PARAM_LAMBDA<ValueType>::MatchesFile( JSON_SETTINGS* aSettings ) const
{
if( std::is_same<ValueType, nlohmann::json>::value )
{
if( OPT<nlohmann::json> optval = aSettings->GetJson( m_path ) )
return *optval == m_getter();
}
else
{
if( OPT<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
return *optval == m_getter();
}
// Not in file
return false;
}
// Instantiate all required templates here to allow reducing scope of json.hpp
template class PARAM_LAMBDA<bool>;
template class PARAM_LAMBDA<int>;
template class PARAM_LAMBDA<nlohmann::json>;
template class PARAM_LAMBDA<std::string>;
template <typename ValueType>
void PARAM_LIST<ValueType>::Load( JSON_SETTINGS* aSettings, bool aResetIfMissing ) const
{
if( m_readOnly )
return;
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
std::vector<ValueType> val;
if( js->is_array() )
{
for( const auto& el : js->items() )
val.push_back( el.value().get<ValueType>() );
}
*m_ptr = val;
}
else if( aResetIfMissing )
*m_ptr = m_default;
}
template <typename ValueType>
void PARAM_LIST<ValueType>::Store( JSON_SETTINGS* aSettings ) const
{
nlohmann::json js = nlohmann::json::array();
for( const auto& el : *m_ptr )
js.push_back( el );
aSettings->Set<nlohmann::json>( m_path, js );
}
template <typename ValueType>
bool PARAM_LIST<ValueType>::MatchesFile( JSON_SETTINGS* aSettings ) const
{
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_array() )
{
std::vector<ValueType> val;
for( const auto& el : js->items() )
val.emplace_back( el.value().get<ValueType>() );
return val == *m_ptr;
}
}
return false;
}
template class PARAM_LIST<int>;
template class PARAM_LIST<double>;
template class PARAM_LIST<wxString>;
template class PARAM_LIST<KIGFX::COLOR4D>;
template class PARAM_LIST<FILE_INFO_PAIR>;
void PARAM_PATH_LIST::Store( JSON_SETTINGS* aSettings ) const
{
nlohmann::json js = nlohmann::json::array();
for( const auto& el : *m_ptr )
js.push_back( toFileFormat( el ) );
aSettings->Set<nlohmann::json>( m_path, js );
}
bool PARAM_PATH_LIST::MatchesFile( JSON_SETTINGS* aSettings ) const
{
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_array() )
{
std::vector<wxString> val;
for( const auto& el : js->items() )
val.emplace_back( fromFileFormat( el.value().get<wxString>() ) );
return val == *m_ptr;
}
}
return false;
}
template <typename Value>
void PARAM_MAP<Value>::Load( JSON_SETTINGS* aSettings, bool aResetIfMissing ) const
{
if( m_readOnly )
return;
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_object() )
{
m_ptr->clear();
for( const auto& el : js->items() )
( *m_ptr )[el.key()] = el.value().get<Value>();
}
}
else if( aResetIfMissing )
*m_ptr = m_default;
}
template <typename Value>
void PARAM_MAP<Value>::Store( JSON_SETTINGS* aSettings ) const
{
nlohmann::json js( {} );
for( const auto& el : *m_ptr )
js[el.first] = el.second;
aSettings->Set<nlohmann::json>( m_path, js );
}
template <typename Value>
bool PARAM_MAP<Value>::MatchesFile( JSON_SETTINGS* aSettings ) const
{
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_object() )
{
if( m_ptr->size() != js->size() )
return false;
std::map<std::string, Value> val;
for( const auto& el : js->items() )
val[el.key()] = el.value().get<Value>();
return val == *m_ptr;
}
}
return false;
}
template class PARAM_MAP<int>;
template class PARAM_MAP<double>;
template class PARAM_MAP<bool>;
void PARAM_WXSTRING_MAP::Load( JSON_SETTINGS* aSettings, bool aResetIfMissing ) const
{
if( m_readOnly )
return;
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_object() )
{
m_ptr->clear();
for( const auto& el : js->items() )
{
( *m_ptr )[wxString( el.key().c_str(), wxConvUTF8 )] = el.value().get<wxString>();
}
}
}
else if( aResetIfMissing )
*m_ptr = m_default;
}
void PARAM_WXSTRING_MAP::Store( JSON_SETTINGS* aSettings ) const
{
nlohmann::json js( {} );
for( const auto& el : *m_ptr )
{
std::string key( el.first.ToUTF8() );
js[key] = el.second;
}
aSettings->Set<nlohmann::json>( m_path, js );
}
bool PARAM_WXSTRING_MAP::MatchesFile( JSON_SETTINGS* aSettings ) const
{
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_object() )
{
if( m_ptr->size() != js->size() )
return false;
std::map<wxString, wxString> val;
for( const auto& el : js->items() )
{
wxString key( el.key().c_str(), wxConvUTF8 );
val[key] = el.value().get<wxString>();
}
return val == *m_ptr;
}
}
return false;
}

View File

@ -41,6 +41,7 @@
#include <project/project_local_settings.h> #include <project/project_local_settings.h>
#include <settings/color_settings.h> #include <settings/color_settings.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
@ -325,7 +326,8 @@ void SETTINGS_MANAGER::SaveColorSettings( COLOR_SETTINGS* aSettings, const std::
} }
) != m_color_settings.end() ); ) != m_color_settings.end() );
nlohmann::json::json_pointer ptr = JSON_SETTINGS::PointerFromString( aNamespace ); if( aSettings->IsReadOnly() )
return;
if( !aSettings->Store() ) if( !aSettings->Store() )
{ {
@ -334,17 +336,17 @@ void SETTINGS_MANAGER::SaveColorSettings( COLOR_SETTINGS* aSettings, const std::
return; return;
} }
wxASSERT( aSettings->contains( ptr ) ); wxASSERT( aSettings->Contains( aNamespace ) );
wxLogTrace( traceSettings, "Saving color scheme %s, preserving %s", aSettings->GetFilename(), wxLogTrace( traceSettings, "Saving color scheme %s, preserving %s", aSettings->GetFilename(),
aNamespace ); aNamespace );
nlohmann::json backup = aSettings->at( ptr ); nlohmann::json backup = aSettings->At( aNamespace );
wxString path = GetColorSettingsPath(); wxString path = GetColorSettingsPath();
aSettings->LoadFromFile( path ); aSettings->LoadFromFile( path );
( *aSettings )[ptr].update( backup ); ( *aSettings->Internals() )[aNamespace].update( backup );
aSettings->Load(); aSettings->Load();
aSettings->SaveToFile( path, true ); aSettings->SaveToFile( path, true );

View File

@ -30,6 +30,7 @@
#include <macros.h> #include <macros.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <wx/config.h> #include <wx/config.h>
@ -405,16 +406,16 @@ bool EESCHEMA_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
// Now modify the loaded grid selection, because in earlier versions the grids index was shared // Now modify the loaded grid selection, because in earlier versions the grids index was shared
// between all applications and started at 1000 mils. There is a 4-position offset between // between all applications and started at 1000 mils. There is a 4-position offset between
// this index and the possible eeschema grids list that we have to subtract. // this index and the possible eeschema grids list that we have to subtract.
nlohmann::json::json_pointer gridSizePtr = PointerFromString( "window.grid.last_size" ); std::string gridSizePtr = "window.grid.last_size";
try if( OPT<int> currentSize = Get<int>( gridSizePtr ) )
{ {
( *this )[gridSizePtr] = ( *this )[gridSizePtr].get<int>() - 4; Set( gridSizePtr, *currentSize - 4 );
} }
catch( ... ) else
{ {
// Otherwise, default grid size should be 50 mils; index 1 // Otherwise, default grid size should be 50 mils; index 1
( *this )[gridSizePtr] = 1; Set( gridSizePtr, 1 );
} }
ret &= fromLegacy<bool>( aCfg, "FootprintPreview", "appearance.footprint_preview" ); ret &= fromLegacy<bool>( aCfg, "FootprintPreview", "appearance.footprint_preview" );
@ -497,8 +498,8 @@ bool EESCHEMA_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
} }
} }
( *this )[PointerFromString( "netlist.custom_command_titles" )] = js_title; Set( "netlist.custom_command_titles", js_title );
( *this )[PointerFromString( "netlist.custom_command_paths" )] = js_cmd; Set( "netlist.custom_command_paths", js_cmd );
} }
{ {
@ -518,11 +519,11 @@ bool EESCHEMA_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
if( aCfg->Read( key, &value ) ) if( aCfg->Read( key, &value ) )
{ {
std::string key_utf( key.ToUTF8() ); std::string key_utf( key.ToUTF8() );
js[PointerFromString( key_utf )] = value; js[JSON_SETTINGS_INTERNALS::PointerFromString( key_utf )] = value;
} }
} }
( *this )[PointerFromString( "field_editor.fields_show" ) ] = js; Set( "field_editor.fields_show", js );
aCfg->SetPath( "../GroupBy" ); aCfg->SetPath( "../GroupBy" );
@ -531,11 +532,11 @@ bool EESCHEMA_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
if( aCfg->Read( key, &value ) ) if( aCfg->Read( key, &value ) )
{ {
std::string key_utf( key.ToUTF8() ); std::string key_utf( key.ToUTF8() );
js[PointerFromString( key_utf )] = value; js[JSON_SETTINGS_INTERNALS::PointerFromString( key_utf )] = value;
} }
} }
( *this )[PointerFromString( "field_editor.fields_group_by" ) ] = js; Set( "field_editor.fields_group_by", js );
aCfg->SetPath( "../.." ); aCfg->SetPath( "../.." );
} }
@ -628,7 +629,7 @@ bool EESCHEMA_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
Pgm().GetSettingsManager().SaveColorSettings( cs, "schematic" ); Pgm().GetSettingsManager().SaveColorSettings( cs, "schematic" );
( *this )[PointerFromString( "appearance.color_theme" )] = cs->GetFilename(); Set( "appearance.color_theme", cs->GetFilename() );
// LibEdit settings were stored with eeschema. If eeschema is the first app to run, // LibEdit settings were stored with eeschema. If eeschema is the first app to run,
// we need to migrate the LibEdit settings here // we need to migrate the LibEdit settings here
@ -668,12 +669,10 @@ std::vector<EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS> EESCHEMA_SETTINGS::DefaultBo
bool EESCHEMA_SETTINGS::migrateBomSettings() bool EESCHEMA_SETTINGS::migrateBomSettings()
{ {
nlohmann::json::json_pointer ptr = PointerFromString( "bom.plugins" ); if( !Contains( "bom.plugins" ) )
if( !contains( ptr ) )
return false; return false;
wxString list = at( ptr ).get<wxString>(); wxString list = Get<wxString>( "bom.plugins" ).value();
BOM_CFG_PARSER cfg_parser( &m_BomPanel.plugins, TO_UTF8( list ), wxT( "plugins" ) ); BOM_CFG_PARSER cfg_parser( &m_BomPanel.plugins, TO_UTF8( list ), wxT( "plugins" ) );
@ -687,7 +686,7 @@ bool EESCHEMA_SETTINGS::migrateBomSettings()
} }
// Parser will have loaded up our array, let's dump it out to JSON // Parser will have loaded up our array, let's dump it out to JSON
at( ptr ) = bomSettingsToJson(); At( "bom.plugins" ) = bomSettingsToJson();
return true; return true;
} }

View File

@ -23,6 +23,7 @@
#include <schematic.h> #include <schematic.h>
#include <sch_marker.h> #include <sch_marker.h>
#include <sch_screen.h> #include <sch_screen.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>

View File

@ -28,6 +28,7 @@
#include <kiface_i.h> #include <kiface_i.h>
#include <macros.h> #include <macros.h>
#include <schematic_settings.h> #include <schematic_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <sim/spice_settings.h> #include <sim/spice_settings.h>

View File

@ -92,16 +92,16 @@ bool SYMBOL_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
// Now modify the loaded grid selection, because in earlier versions the grids index was shared // Now modify the loaded grid selection, because in earlier versions the grids index was shared
// between all applications and started at 1000 mils. There is a 4-position offset between // between all applications and started at 1000 mils. There is a 4-position offset between
// this index and the possible eeschema grids list that we have to subtract. // this index and the possible eeschema grids list that we have to subtract.
nlohmann::json::json_pointer gridSizePtr = PointerFromString( "window.grid.last_size" ); std::string gridSizePtr = "window.grid.last_size";
try if( OPT<int> currentSize = Get<int>( gridSizePtr ) )
{ {
( *this )[gridSizePtr] = ( *this )[gridSizePtr].get<int>() - 4; Set( gridSizePtr, *currentSize - 4 );
} }
catch( ... ) else
{ {
// Otherwise, default grid size should be 50 mils; index 1 // Otherwise, default grid size should be 50 mils; index 1
( *this )[gridSizePtr] = 1; Set( gridSizePtr, 1 );
} }
ret &= fromLegacy<int>( aCfg, "DefaultWireWidth", "defaults.line_width" ); ret &= fromLegacy<int>( aCfg, "DefaultWireWidth", "defaults.line_width" );

View File

@ -25,6 +25,7 @@
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <wx/config.h> #include <wx/config.h>
@ -99,7 +100,7 @@ bool GERBVIEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
aCfg->SetPath( ".." ); aCfg->SetPath( ".." );
( *this )[PointerFromString( aDest )] = js; Set( aDest, js );
}; };
migrate_files( "drl_files", "system.drill_file_history" ); migrate_files( "drl_files", "system.drill_file_history" );
@ -109,15 +110,14 @@ bool GERBVIEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
{ {
wxString key; wxString key;
int value = 0; int value = 0;
nlohmann::json::json_pointer ptr = PointerFromString( "gerber_to_pcb_layers" );
( *this )[ptr] = nlohmann::json::array(); At( "gerber_to_pcb_layers" ) = nlohmann::json::array();
for( int i = 0; i < GERBER_DRAWLAYERS_COUNT; i++ ) for( int i = 0; i < GERBER_DRAWLAYERS_COUNT; i++ )
{ {
key.Printf( "GbrLyr%dToPcb", i ); key.Printf( "GbrLyr%dToPcb", i );
aCfg->Read( key, &value, UNSELECTED_LAYER ); aCfg->Read( key, &value, UNSELECTED_LAYER );
( *this )[ptr].emplace_back( value ); At( "gerber_to_pcb_layers" ).emplace_back( value );
} }
} }
@ -147,7 +147,7 @@ bool GERBVIEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
Pgm().GetSettingsManager().SaveColorSettings( cs, "gerbview" ); Pgm().GetSettingsManager().SaveColorSettings( cs, "gerbview" );
( *this )[PointerFromString( "appearance.color_theme" )] = cs->GetFilename(); Set( "appearance.color_theme", cs->GetFilename() );
return ret; return ret;
} }

View File

@ -24,6 +24,9 @@
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
#include <settings/parameters.h> #include <settings/parameters.h>
// Can be removed by refactoring PARAM_LAYER_PRESET
#include <nlohmann/json.hpp>
/** /**
* This file contains data structures that are saved in the project file or project local settings * This file contains data structures that are saved in the project file or project local settings
* file that are specific to PcbNew. This is done so that these structures are available in common. * file that are specific to PcbNew. This is done so that these structures are available in common.

View File

@ -21,6 +21,8 @@
#ifndef _COLOR_SETTINGS_H #ifndef _COLOR_SETTINGS_H
#define _COLOR_SETTINGS_H #define _COLOR_SETTINGS_H
#include <unordered_map>
#include <gal/color4d.h> #include <gal/color4d.h>
#include <settings/json_settings.h> #include <settings/json_settings.h>
#include <settings/parameters.h> #include <settings/parameters.h>

View File

@ -23,11 +23,11 @@
#include <core/wx_stl_compat.h> #include <core/wx_stl_compat.h>
#include <nlohmann/json.hpp>
#include <utility> #include <utility>
#include <wx/string.h> #include <wx/string.h>
#include <core/optional.h> #include <core/optional.h>
#include <nlohmann/json_fwd.hpp>
class wxConfigBase; class wxConfigBase;
class NESTED_SETTINGS; class NESTED_SETTINGS;
@ -52,9 +52,14 @@ enum class SETTINGS_LOC {
}; };
class JSON_SETTINGS : public nlohmann::json /// pimpl to allow hiding json.hpp
class JSON_SETTINGS_INTERNALS;
class JSON_SETTINGS
{ {
public: public:
friend class NESTED_SETTINGS;
JSON_SETTINGS( const wxString& aFilename, SETTINGS_LOC aLocation, int aSchemaVersion ) : JSON_SETTINGS( const wxString& aFilename, SETTINGS_LOC aLocation, int aSchemaVersion ) :
JSON_SETTINGS( aFilename, aLocation, aSchemaVersion, true, true, true ) {} JSON_SETTINGS( aFilename, aLocation, aSchemaVersion, true, true, true ) {}
@ -76,6 +81,17 @@ public:
bool IsReadOnly() const { return !m_writeFile; } bool IsReadOnly() const { return !m_writeFile; }
void SetReadOnly( bool aReadOnly ) { m_writeFile = !aReadOnly; } void SetReadOnly( bool aReadOnly ) { m_writeFile = !aReadOnly; }
/**
* Wrappers for the underlying JSON API so that most consumers don't need json.hpp
* All of these functions take a string that is passed to PointerFromString internally.
*/
nlohmann::json& At( const std::string& aPath );
bool Contains( const std::string& aPath ) const;
size_t Count( const std::string& aPath ) const;
JSON_SETTINGS_INTERNALS* Internals();
/** /**
* Updates the parameters of this object based on the current JSON document contents * Updates the parameters of this object based on the current JSON document contents
*/ */
@ -130,21 +146,7 @@ c * @return true if the file was saved
* @return a value from within this document * @return a value from within this document
*/ */
template<typename ValueType> template<typename ValueType>
OPT<ValueType> Get( const std::string& aPath ) const OPT<ValueType> Get( const std::string& aPath ) const;
{
if( OPT<nlohmann::json> ret = GetJson( aPath ) )
{
try
{
return ret->get<ValueType>();
}
catch( ... )
{
}
}
return NULLOPT;
}
/** /**
* Stores a value into the JSON document * Stores a value into the JSON document
@ -154,10 +156,7 @@ c * @return true if the file was saved
* @param aVal is the value to store * @param aVal is the value to store
*/ */
template<typename ValueType> template<typename ValueType>
void Set( const std::string& aPath, ValueType aVal ) void Set( const std::string& aPath, ValueType aVal );
{
( *this )[PointerFromString( aPath ) ] = aVal;
}
/** /**
* Migrates the schema of this settings from the version in the file to the latest version * Migrates the schema of this settings from the version in the file to the latest version
@ -199,13 +198,6 @@ c * @return true if the file was saved
m_manager = aManager; m_manager = aManager;
} }
/**
* Builds a JSON pointer based on a given string
* @param aPath is the path in the form "key1.key2.key3"
* @return a JSON pointer that can be used to index into a JSON object
*/
static nlohmann::json::json_pointer PointerFromString( std::string aPath );
/** /**
* Sets the given string if the given key/path is present * Sets the given string if the given key/path is present
* @param aObj is the source object * @param aObj is the source object
@ -329,11 +321,10 @@ protected:
/// A pointer to the settings manager managing this file (may be null) /// A pointer to the settings manager managing this file (may be null)
SETTINGS_MANAGER* m_manager; SETTINGS_MANAGER* m_manager;
/// A list of JSON pointers that are preserved during a read-update-write to disk
std::vector<nlohmann::json::json_pointer> m_preserved_paths;
/// A map of starting schema version to a pair of <ending version, migrator function> /// A map of starting schema version to a pair of <ending version, migrator function>
std::map<int, std::pair<int, std::function<bool()>>> m_migrators; std::map<int, std::pair<int, std::function<bool()>>> m_migrators;
std::unique_ptr<JSON_SETTINGS_INTERNALS> m_internals;
}; };
// Specializations to allow conversion between wxString and std::string via JSON_SETTINGS API // Specializations to allow conversion between wxString and std::string via JSON_SETTINGS API

View File

@ -0,0 +1,67 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2021 Jon Evans <jon@craftyjon.com>
* Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KICAD_JSON_SETTINGS_INTERNALS_H
#define KICAD_JSON_SETTINGS_INTERNALS_H
// This is a pretty heavy file. Try to use json_fwd.hpp most places.
#include <nlohmann/json.hpp>
class JSON_SETTINGS_INTERNALS : public nlohmann::json
{
friend class JSON_SETTINGS;
public:
JSON_SETTINGS_INTERNALS() :
nlohmann::json()
{}
/**
* Builds a JSON pointer based on a given string
* @param aPath is the path in the form "key1.key2.key3"
* @return a JSON pointer that can be used to index into a JSON object
*/
static nlohmann::json::json_pointer PointerFromString( std::string aPath );
template<typename ValueType>
void SetFromString( const std::string& aPath, ValueType aVal )
{
// Calls the overload below, which will convert from dotted string to JSON pointer
( *this )[aPath] = aVal;
}
template<typename ValueType>
ValueType Get( const std::string& aPath ) const
{
return at( PointerFromString( aPath ) ).get<ValueType>();
}
nlohmann::json& At( const std::string& aPath )
{
return at( PointerFromString( aPath ) );
}
nlohmann::json& operator[]( const std::string& aPath )
{
return nlohmann::json::operator[]( PointerFromString( aPath ) );
}
};
#endif // KICAD_JSON_SETTINGS_INTERNALS_H

View File

@ -305,26 +305,7 @@ public:
m_setter( aSetter ) m_setter( aSetter )
{ } { }
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override;
{
if( m_readOnly )
return;
if( std::is_same<ValueType, nlohmann::json>::value )
{
if( OPT<nlohmann::json> optval = aSettings->GetJson( m_path ) )
m_setter( *optval );
else
m_setter( m_default );
}
else
{
if( OPT<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
m_setter( *optval );
else
m_setter( m_default );
}
}
void Store( JSON_SETTINGS* aSettings ) const override void Store( JSON_SETTINGS* aSettings ) const override
{ {
@ -352,22 +333,7 @@ public:
return m_getter() == m_default; return m_getter() == m_default;
} }
bool MatchesFile( JSON_SETTINGS* aSettings ) const override bool MatchesFile( JSON_SETTINGS* aSettings ) const override;
{
if( std::is_same<ValueType, nlohmann::json>::value )
{
if( OPT<nlohmann::json> optval = aSettings->GetJson( m_path ) )
return *optval == m_getter();
}
else
{
if( OPT<ValueType> optval = aSettings->Get<ValueType>( m_path ) )
return *optval == m_getter();
}
// Not in file
return false;
}
private: private:
ValueType m_default; ValueType m_default;
@ -488,36 +454,9 @@ public:
m_default( aDefault ) m_default( aDefault )
{ } { }
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override;
{
if( m_readOnly )
return;
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) ) void Store( JSON_SETTINGS* aSettings) const override;
{
std::vector<Type> val;
if( js->is_array() )
{
for( const auto& el : js->items() )
val.push_back( el.value().get<Type>() );
}
*m_ptr = val;
}
else if( aResetIfMissing )
*m_ptr = m_default;
}
void Store( JSON_SETTINGS* aSettings) const override
{
nlohmann::json js = nlohmann::json::array();
for( const auto& el : *m_ptr )
js.push_back( el );
aSettings->Set<nlohmann::json>( m_path, js );
}
void SetDefault() override void SetDefault() override
{ {
@ -529,23 +468,7 @@ public:
return *m_ptr == m_default; return *m_ptr == m_default;
} }
bool MatchesFile( JSON_SETTINGS* aSettings ) const override bool MatchesFile( JSON_SETTINGS* aSettings ) const override;
{
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_array() )
{
std::vector<Type> val;
for( const auto& el : js->items() )
val.emplace_back( el.value().get<Type>() );
return val == *m_ptr;
}
}
return false;
}
protected: protected:
std::vector<Type>* m_ptr; std::vector<Type>* m_ptr;
@ -581,33 +504,9 @@ public:
( *m_ptr )[i] = fromFileFormat( ( *m_ptr )[i] ); ( *m_ptr )[i] = fromFileFormat( ( *m_ptr )[i] );
} }
void Store( JSON_SETTINGS* aSettings) const override void Store( JSON_SETTINGS* aSettings) const override;
{
nlohmann::json js = nlohmann::json::array();
for( const auto& el : *m_ptr ) bool MatchesFile( JSON_SETTINGS* aSettings ) const override;
js.push_back( toFileFormat( el ) );
aSettings->Set<nlohmann::json>( m_path, js );
}
bool MatchesFile( JSON_SETTINGS* aSettings ) const override
{
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_array() )
{
std::vector<wxString> val;
for( const auto& el : js->items() )
val.emplace_back( fromFileFormat( el.value().get<wxString>() ) );
return val == *m_ptr;
}
}
return false;
}
private: private:
wxString toFileFormat( const wxString& aString ) const wxString toFileFormat( const wxString& aString ) const
@ -651,34 +550,9 @@ public:
m_default( aDefault ) m_default( aDefault )
{ } { }
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override;
{
if( m_readOnly )
return;
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) ) void Store( JSON_SETTINGS* aSettings) const override;
{
if( js->is_object() )
{
m_ptr->clear();
for( const auto& el : js->items() )
( *m_ptr )[ el.key() ] = el.value().get<Value>();
}
}
else if( aResetIfMissing )
*m_ptr = m_default;
}
void Store( JSON_SETTINGS* aSettings) const override
{
nlohmann::json js( {} );
for( const auto& el : *m_ptr )
js[ el.first ] = el.second;
aSettings->Set<nlohmann::json>( m_path, js );
}
virtual void SetDefault() override virtual void SetDefault() override
{ {
@ -690,26 +564,7 @@ public:
return *m_ptr == m_default; return *m_ptr == m_default;
} }
bool MatchesFile( JSON_SETTINGS* aSettings ) const override bool MatchesFile( JSON_SETTINGS* aSettings ) const override;
{
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_object() )
{
if( m_ptr->size() != js->size() )
return false;
std::map<std::string, Value> val;
for( const auto& el : js->items() )
val[ el.key() ] = el.value().get<Value>();
return val == *m_ptr;
}
}
return false;
}
private: private:
std::map<std::string, Value>* m_ptr; std::map<std::string, Value>* m_ptr;
@ -732,40 +587,9 @@ public:
m_default( aDefault ) m_default( aDefault )
{ } { }
void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override void Load( JSON_SETTINGS* aSettings, bool aResetIfMissing = true ) const override;
{
if( m_readOnly )
return;
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) ) void Store( JSON_SETTINGS* aSettings) const override;
{
if( js->is_object() )
{
m_ptr->clear();
for( const auto& el : js->items() )
{
( *m_ptr )[wxString( el.key().c_str(), wxConvUTF8 )] =
el.value().get<wxString>();
}
}
}
else if( aResetIfMissing )
*m_ptr = m_default;
}
void Store( JSON_SETTINGS* aSettings) const override
{
nlohmann::json js( {} );
for( const auto& el : *m_ptr )
{
std::string key( el.first.ToUTF8() );
js[ key ] = el.second;
}
aSettings->Set<nlohmann::json>( m_path, js );
}
virtual void SetDefault() override virtual void SetDefault() override
{ {
@ -777,29 +601,7 @@ public:
return *m_ptr == m_default; return *m_ptr == m_default;
} }
bool MatchesFile( JSON_SETTINGS* aSettings ) const override bool MatchesFile( JSON_SETTINGS* aSettings ) const override;
{
if( OPT<nlohmann::json> js = aSettings->GetJson( m_path ) )
{
if( js->is_object() )
{
if( m_ptr->size() != js->size() )
return false;
std::map<wxString, wxString> val;
for( const auto& el : js->items() )
{
wxString key( el.key().c_str(), wxConvUTF8 );
val[key] = el.value().get<wxString>();
}
return val == *m_ptr;
}
}
return false;
}
private: private:
std::map<wxString, wxString>* m_ptr; std::map<wxString, wxString>* m_ptr;

View File

@ -21,6 +21,7 @@
#ifndef _SETTINGS_MANAGER_H #ifndef _SETTINGS_MANAGER_H
#define _SETTINGS_MANAGER_H #define _SETTINGS_MANAGER_H
#include <algorithm>
#include <typeinfo> #include <typeinfo>
#include <core/wx_stl_compat.h> // for wxString hash #include <core/wx_stl_compat.h> // for wxString hash
#include <settings/color_settings.h> #include <settings/color_settings.h>

View File

@ -24,6 +24,7 @@
#include <array> #include <array>
#include <pcb_calculator_settings.h> #include <pcb_calculator_settings.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <wx/config.h> #include <wx/config.h>
@ -214,7 +215,9 @@ bool PCB_CALCULATOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
ret &= fromLegacy<int>( aCfg, "Att_selection", "attenuators.type" ); ret &= fromLegacy<int>( aCfg, "Att_selection", "attenuators.type" );
{ {
nlohmann::json::json_pointer ptr = PointerFromString( "attenuators" ); nlohmann::json::json_pointer ptr =
JSON_SETTINGS_INTERNALS::PointerFromString( "attenuators" );
const std::array<std::string, 4> att_names = { "att_pi", "att_tee", const std::array<std::string, 4> att_names = { "att_pi", "att_tee",
"att_bridge", "att_splitter" }; "att_bridge", "att_splitter" };
double val = 0; double val = 0;
@ -225,13 +228,13 @@ bool PCB_CALCULATOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
ptr.push_back( att ); ptr.push_back( att );
if( aCfg->Read( "Attenuation", &val ) ) if( aCfg->Read( "Attenuation", &val ) )
( *this )[ptr]["attenuation"] = val; ( *m_internals )[ptr]["attenuation"] = val;
if( aCfg->Read( "Zin", &val ) ) if( aCfg->Read( "Zin", &val ) )
( *this )[ptr]["zin"] = val; ( *m_internals )[ptr]["zin"] = val;
if( aCfg->Read( "Zout", &val ) ) if( aCfg->Read( "Zout", &val ) )
( *this )[ptr]["zout"] = val; ( *m_internals )[ptr]["zout"] = val;
ptr.pop_back(); ptr.pop_back();
aCfg->SetPath( "../.." ); aCfg->SetPath( "../.." );
@ -269,7 +272,9 @@ bool PCB_CALCULATOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
ret &= fromLegacy<int>( aCfg, "Transline_selection", "trans_line.selection" ); ret &= fromLegacy<int>( aCfg, "Transline_selection", "trans_line.selection" );
{ {
nlohmann::json::json_pointer ptr = PointerFromString( "trans_line" ); nlohmann::json::json_pointer ptr =
JSON_SETTINGS_INTERNALS::PointerFromString( "trans_line" );
wxString key; wxString key;
double value = 0; double value = 0;
int units = 0; int units = 0;
@ -295,7 +300,7 @@ bool PCB_CALCULATOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
aCfg->Read( key, &units ); aCfg->Read( key, &units );
ptr.push_back( "units" ); ptr.push_back( "units" );
( *this )[ptr].push_back( { { dest.ToStdString(), units } } ); ( *m_internals )[ptr].push_back( { { dest.ToStdString(), units } } );
ptr.pop_back(); ptr.pop_back();
} }
@ -304,7 +309,7 @@ bool PCB_CALCULATOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
aCfg->Read( key, &value ); aCfg->Read( key, &value );
ptr.push_back( "values" ); ptr.push_back( "values" );
( *this )[ptr].push_back( { { dest.ToStdString(), value } } ); ( *m_internals )[ptr].push_back( { { dest.ToStdString(), value } } );
ptr.pop_back(); ptr.pop_back();
} }

View File

@ -25,6 +25,7 @@
#define _PCB_CALCULATOR_SETTINGS_H #define _PCB_CALCULATOR_SETTINGS_H
#include <array> #include <array>
#include <unordered_map>
#include <settings/app_settings.h> #include <settings/app_settings.h>
class PCB_CALCULATOR_SETTINGS : public APP_SETTINGS_BASE class PCB_CALCULATOR_SETTINGS : public APP_SETTINGS_BASE

View File

@ -28,6 +28,7 @@
#include <board_design_settings.h> #include <board_design_settings.h>
#include <drc/drc_item.h> #include <drc/drc_item.h>
#include <drc/drc_engine.h> #include <drc/drc_engine.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <project/project_file.h> #include <project/project_file.h>
#include <advanced_config.h> #include <advanced_config.h>
@ -622,10 +623,10 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
try try
{ {
at( "rules" ).erase( "solder_mask_clearance" ); At( "rules" ).erase( "solder_mask_clearance" );
at( "rules" ).erase( "solder_mask_min_width" ); At( "rules" ).erase( "solder_mask_min_width" );
at( "rules" ).erase( "solder_paste_clearance" ); At( "rules" ).erase( "solder_paste_clearance" );
at( "rules" ).erase( "solder_paste_margin_ratio" ); At( "rules" ).erase( "solder_paste_margin_ratio" );
} }
catch( ... ) catch( ... )
{} {}
@ -765,19 +766,19 @@ bool BOARD_DESIGN_SETTINGS::migrateSchema0to1()
* 1: Mils * 1: Mils
* 2: Millimetres * 2: Millimetres
*/ */
nlohmann::json::json_pointer units_ptr( "/defaults/dimension_units" ); std::string units_ptr( "defaults.dimension_units" );
nlohmann::json::json_pointer precision_ptr( "/defaults/dimension_precision" ); std::string precision_ptr( "defaults.dimension_precision" );
if( !( contains( units_ptr ) && contains( precision_ptr ) && if( !( Contains( units_ptr ) && Contains( precision_ptr ) &&
at( units_ptr ).is_number_integer() && At( units_ptr ).is_number_integer() &&
at( precision_ptr ).is_number_integer() ) ) At( precision_ptr ).is_number_integer() ) )
{ {
// if either is missing or invalid, migration doesn't make sense // if either is missing or invalid, migration doesn't make sense
return true; return true;
} }
int units = at( units_ptr ).get<int>(); int units = Get<int>( units_ptr ).value();
int precision = at( precision_ptr ).get<int>(); int precision = Get<int>( precision_ptr ).value();
// The enum maps directly to precision if the units is mils // The enum maps directly to precision if the units is mils
int extraDigits = 0; int extraDigits = 0;
@ -791,7 +792,7 @@ bool BOARD_DESIGN_SETTINGS::migrateSchema0to1()
precision += extraDigits; precision += extraDigits;
( *this )[precision_ptr] = precision; Set( precision_ptr, precision );
return true; return true;
} }
@ -823,36 +824,35 @@ bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
std::string bp = "board.design_settings.rule_severities."; std::string bp = "board.design_settings.rule_severities.";
std::string rs = "rule_severities."; std::string rs = "rule_severities.";
if( OPT<bool> v = if( OPT<bool> v = project->Get<bool>( bp + "legacy_no_courtyard_defined" ) )
project->Get<bool>( PointerFromString( bp + "legacy_no_courtyard_defined" ) ) )
{ {
if( *v ) if( *v )
( *this )[PointerFromString( rs + drcName( DRCE_MISSING_COURTYARD ) )] = "error"; Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
else else
( *this )[PointerFromString( rs + drcName( DRCE_MISSING_COURTYARD ) )] = "ignore"; Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
project->erase( PointerFromString( bp + "legacy_no_courtyard_defined" ) ); project->Internals()->erase( m_internals->PointerFromString( bp + "legacy_no_courtyard_defined" ) );
migrated = true; migrated = true;
} }
if( OPT<bool> v = project->Get<bool>( PointerFromString( bp + "legacy_courtyards_overlap" ) ) ) if( OPT<bool> v = project->Get<bool>( bp + "legacy_courtyards_overlap" ) )
{ {
if( *v ) if( *v )
( *this )[PointerFromString( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ) )] = "error"; Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
else else
( *this )[PointerFromString( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ) )] = "ignore"; Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
project->erase( PointerFromString( bp + "legacy_courtyards_overlap" ) ); project->Internals()->erase( JSON_SETTINGS_INTERNALS::PointerFromString( bp + "legacy_courtyards_overlap" ) );
migrated = true; migrated = true;
} }
if( project->contains( "legacy" ) ) if( Contains( "legacy" ) )
{ {
// This defaults to false for new boards, but version 5.1.x and prior kept the fillets // This defaults to false for new boards, but version 5.1.x and prior kept the fillets
// so we do the same for legacy boards. // so we do the same for legacy boards.
m_ZoneKeepExternalFillets = true; m_ZoneKeepExternalFillets = true;
project->at( "legacy" ).erase( "pcbnew" ); project->At( "legacy" ).erase( "pcbnew" );
} }
// Now that we have everything, we need to load again // Now that we have everything, we need to load again

View File

@ -23,6 +23,7 @@
#include <layers_id_colors_and_visibility.h> #include <layers_id_colors_and_visibility.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <settings/common_settings.h> #include <settings/common_settings.h>
#include <settings/json_settings_internals.h>
#include <settings/parameters.h> #include <settings/parameters.h>
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
#include <wx/config.h> #include <wx/config.h>
@ -317,7 +318,7 @@ bool FOOTPRINT_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
{ "", true, F_Fab } { "", true, F_Fab }
} ); } );
( *this )[PointerFromString( "design_settings.default_footprint_text_items" )] = textItems; Set( "design_settings.default_footprint_text_items", textItems );
ret &= fromLegacyString( aCfg, "FpEditorRefDefaultText", "design_settings.default_footprint_text_items.0.0" ); ret &= fromLegacyString( aCfg, "FpEditorRefDefaultText", "design_settings.default_footprint_text_items.0.0" );
ret &= fromLegacy<bool>( aCfg, "FpEditorRefDefaultVisibility", "design_settings.default_footprint_text_items.0.1" ); ret &= fromLegacy<bool>( aCfg, "FpEditorRefDefaultVisibility", "design_settings.default_footprint_text_items.0.1" );
@ -371,7 +372,7 @@ bool FOOTPRINT_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
manager.SaveColorSettings( cs, "board" ); manager.SaveColorSettings( cs, "board" );
( *this )[PointerFromString( "appearance.color_theme" )] = "user_footprints"; ( *m_internals )[m_internals->PointerFromString( "appearance.color_theme" )] = "user_footprints";
double x, y; double x, y;
f = "ModEditFrame"; f = "ModEditFrame";
@ -385,8 +386,8 @@ bool FOOTPRINT_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
x = From_User_Unit( u, x ); x = From_User_Unit( u, x );
y = From_User_Unit( u, y ); y = From_User_Unit( u, y );
( *this )[PointerFromString( "window.grid.user_grid_x" )] = StringFromValue( u, x ); Set( "window.grid.user_grid_x", StringFromValue( u, x ) );
( *this )[PointerFromString( "window.grid.user_grid_y" )] = StringFromValue( u, y ); Set( "window.grid.user_grid_y", StringFromValue( u, y ) );
} }
return ret; return ret;
@ -409,12 +410,12 @@ bool FOOTPRINT_EDITOR_SETTINGS::migrateSchema0to1()
return false; return false;
} }
nlohmann::json::json_pointer theme_ptr( "/appearance/color_theme" ); std::string theme_ptr( "appearance.color_theme" );
if( !count( theme_ptr ) ) if( !Count( theme_ptr ) )
return true; return true;
wxString selected = at( theme_ptr ).get<wxString>(); wxString selected = At( theme_ptr ).get<wxString>();
wxString search = selected + wxT( "_footprints" ); wxString search = selected + wxT( "_footprints" );
for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() ) for( COLOR_SETTINGS* settings : Pgm().GetSettingsManager().GetColorSettingsList() )
@ -423,7 +424,7 @@ bool FOOTPRINT_EDITOR_SETTINGS::migrateSchema0to1()
{ {
wxLogTrace( traceSettings, "Updating footprint editor theme from %s to %s", wxLogTrace( traceSettings, "Updating footprint editor theme from %s to %s",
selected, search ); selected, search );
( *this )[theme_ptr] = search; Set( theme_ptr, search );
return true; return true;
} }
} }

View File

@ -608,7 +608,7 @@ bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
js.push_back( i ); js.push_back( i );
} }
( *this )[PointerFromString( "export_svg.layers" ) ] = js; Set( "export_svg.layers", js );
} }
{ {
@ -639,7 +639,7 @@ bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
} }
} }
( *this )[PointerFromString( "action_plugins" ) ] = js; Set( "action_plugins", js );
} }
// //
@ -706,10 +706,10 @@ bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
const std::string p = "pcbnew.InteractiveRouter."; const std::string p = "pcbnew.InteractiveRouter.";
( *this )[PointerFromString( "tools.pns.meta" )] = nlohmann::json( { Set( "tools.pns.meta", nlohmann::json( {
{ "filename", "pns" }, { "filename", "pns" },
{ "version", 0 } { "version", 0 }
} ); } ) );
ret &= fromLegacy<int>( aCfg, p + "Mode", "tools.pns.mode" ); ret &= fromLegacy<int>( aCfg, p + "Mode", "tools.pns.mode" );
ret &= fromLegacy<int>( aCfg, p + "OptimizerEffort", "tools.pns.effort" ); ret &= fromLegacy<int>( aCfg, p + "OptimizerEffort", "tools.pns.effort" );
@ -728,7 +728,7 @@ bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
ret &= fromLegacy<bool>( aCfg, p + "InlineDragEnabled", "tools.pns.inline_drag" ); ret &= fromLegacy<bool>( aCfg, p + "InlineDragEnabled", "tools.pns.inline_drag" );
// Initialize some new PNS settings to legacy behaviors if coming from legacy // Initialize some new PNS settings to legacy behaviors if coming from legacy
( *this )[PointerFromString( "tools.pns.fix_all_segments" )] = false; Set( "tools.pns.fix_all_segments", false );
// Migrate color settings that were stored in the pcbnew config file // Migrate color settings that were stored in the pcbnew config file
@ -766,7 +766,7 @@ bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
Pgm().GetSettingsManager().SaveColorSettings( cs, "board" ); Pgm().GetSettingsManager().SaveColorSettings( cs, "board" );
( *this )[PointerFromString( "appearance.color_theme" )] = cs->GetFilename(); Set( "appearance.color_theme", cs->GetFilename() );
double x, y; double x, y;
@ -779,8 +779,8 @@ bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
x = From_User_Unit( u, x ); x = From_User_Unit( u, x );
y = From_User_Unit( u, y ); y = From_User_Unit( u, y );
( *this )[PointerFromString( "window.grid.user_grid_x" )] = StringFromValue( u, x ); Set( "window.grid.user_grid_x", StringFromValue( u, x ) );
( *this )[PointerFromString( "window.grid.user_grid_y" )] = StringFromValue( u, y ); Set( "window.grid.user_grid_y", StringFromValue( u, y ) );
} }
// Footprint editor settings were stored in pcbnew config file. Migrate them here. // Footprint editor settings were stored in pcbnew config file. Migrate them here.