diff --git a/3d-viewer/3d_cache/3d_cache.cpp b/3d-viewer/3d_cache/3d_cache.cpp
index 1935b390b5..2ce7c25019 100644
--- a/3d-viewer/3d_cache/3d_cache.cpp
+++ b/3d-viewer/3d_cache/3d_cache.cpp
@@ -57,6 +57,7 @@
 #include <filename_resolver.h>
 #include <pgm_base.h>
 #include <project.h>
+#include <settings/settings_manager.h>
 
 
 #define MASK_3D_CACHE "3D_CACHE"
@@ -793,7 +794,7 @@ S3D_CACHE* PROJECT::Get3DCacheManager( bool aUpdateProjDir )
         cache = new S3D_CACHE();
 
         wxFileName cfgpath;
-        cfgpath.AssignDir( GetKicadConfigPath() );
+        cfgpath.AssignDir( SETTINGS_MANAGER::GetUserSettingsPath() );
         cfgpath.AppendDir( wxT( "3d" ) );
 
         cache->SetProgramBase( &Pgm() );
diff --git a/3d-viewer/3d_cache/3d_plugin_manager.cpp b/3d-viewer/3d_cache/3d_plugin_manager.cpp
index 42a7a73efa..43e490818c 100644
--- a/3d-viewer/3d_cache/3d_plugin_manager.cpp
+++ b/3d-viewer/3d_cache/3d_plugin_manager.cpp
@@ -26,7 +26,6 @@
 #include <iostream>
 #include <sstream>
 
-#include <wx/config.h>
 #include <wx/dir.h>
 #include <wx/dynlib.h>
 #include <wx/filename.h>
diff --git a/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp
index 0b169d5036..250312dd6d 100644
--- a/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp
+++ b/3d-viewer/3d_cache/dialogs/panel_prev_model.cpp
@@ -26,13 +26,14 @@
 
 #include "panel_prev_model.h"
 #include <3d_canvas/eda_3d_canvas.h>
-#include <common_ogl/cogl_att_list.h>
-#include <class_board.h>
 #include <base_units.h>
 #include <bitmaps.h>
+#include <class_board.h>
+#include <common_ogl/cogl_att_list.h>
 #include <dpi_scaling.h>
 #include <pgm_base.h>
 #include <project.h>
+#include <settings/common_settings.h>
 
 
 PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, PCB_BASE_FRAME* aFrame, MODULE* aModule,
@@ -43,9 +44,6 @@ PANEL_PREV_3D::PANEL_PREV_3D( wxWindow* aParent, PCB_BASE_FRAME* aFrame, MODULE*
 
     initPanel();
 
-    // Initialize the color settings to draw the board and the footprint
-    m_dummyBoard->SetGeneralSettings( &aFrame->Settings() );
-
     m_parentModelList = aParentModelList;
 
     m_dummyModule = new MODULE( *aModule );
@@ -109,18 +107,12 @@ void PANEL_PREV_3D::loadCommonSettings()
 {
     wxCHECK_RET( m_previewPane, "Cannot load settings to null canvas" );
 
-    wxConfigBase& cmnCfg = *Pgm().CommonSettings();
+    COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
 
-    {
-        const DPI_SCALING dpi{ &cmnCfg, this };
-        m_previewPane->SetScaleFactor( dpi.GetScaleFactor() );
-    }
+    const DPI_SCALING dpi{ settings, this };
+    m_previewPane->SetScaleFactor( dpi.GetScaleFactor() );
 
-    {
-        bool option;
-        cmnCfg.Read( ENBL_MOUSEWHEEL_PAN_KEY, &option, false );
-        m_settings3Dviewer->SetFlag( FL_MOUSEWHEEL_PANNING, option );
-    }
+    m_settings3Dviewer->SetFlag( FL_MOUSEWHEEL_PANNING, settings->m_Input.mousewheel_pan );
 }
 
 
diff --git a/3d-viewer/3d_canvas/cinfo3d_visu.cpp b/3d-viewer/3d_canvas/cinfo3d_visu.cpp
index 62a1a5b863..8b238a0140 100644
--- a/3d-viewer/3d_canvas/cinfo3d_visu.cpp
+++ b/3d-viewer/3d_canvas/cinfo3d_visu.cpp
@@ -35,6 +35,8 @@
 #include "3d_fastmath.h"
 #include <geometry/geometry_utils.h>
 #include <math/util.h>      // for KiROUND
+#include <pgm_base.h>
+#include <settings/settings_manager.h>
 
 /**
  *  Trace mask used to enable or disable the trace output of this class.
@@ -59,6 +61,9 @@ CINFO3D_VISU::CINFO3D_VISU() :
     m_3D_grid_type     = GRID3D_TYPE::NONE;
     m_drawFlags.resize( FL_LAST, false );
 
+    if( PgmOrNull() )
+        m_colors = Pgm().GetSettingsManager().GetColorSettings();
+
     m_render_engine = RENDER_ENGINE::OPENGL_LEGACY;
     m_material_mode = MATERIAL_MODE::NORMAL;
 
@@ -504,7 +509,7 @@ SFVEC3F CINFO3D_VISU::GetLayerColor( PCB_LAYER_ID aLayerId ) const
 {
     wxASSERT( aLayerId < PCB_LAYER_ID_COUNT );
 
-    const COLOR4D color = m_board->Colors().GetLayerColor( aLayerId );
+    const COLOR4D color = m_colors->GetColor( aLayerId );
 
     return SFVEC3F( color.r, color.g, color.b );
 }
@@ -512,7 +517,7 @@ SFVEC3F CINFO3D_VISU::GetLayerColor( PCB_LAYER_ID aLayerId ) const
 
 SFVEC3F CINFO3D_VISU::GetItemColor( int aItemId ) const
 {
-    return GetColor( m_board->Colors().GetItemColor( aItemId ) );
+    return GetColor( m_colors->GetColor( aItemId ) );
 }
 
 
diff --git a/3d-viewer/3d_canvas/cinfo3d_visu.h b/3d-viewer/3d_canvas/cinfo3d_visu.h
index 366db6df32..b43504ea66 100644
--- a/3d-viewer/3d_canvas/cinfo3d_visu.h
+++ b/3d-viewer/3d_canvas/cinfo3d_visu.h
@@ -51,6 +51,9 @@
 #include <class_module.h>
 #include <reporter.h>
 
+
+class COLOR_SETTINGS;
+
 /// A type that stores a container of 2d objects for each layer id
 typedef std::map< PCB_LAYER_ID, CBVHCONTAINER2D *> MAP_CONTAINER_2D;
 
@@ -127,6 +130,8 @@ class CINFO3D_VISU
      */
     const BOARD *GetBoard() const { return m_board; }
 
+    void SetColorSettings( COLOR_SETTINGS* aSettings ) { m_colors = aSettings; }
+
     /**
      * @brief InitSettings - Function to be called by the render when it need to
      * reload the settings for the board.
@@ -519,6 +524,8 @@ private:
     /// pointer to the 3d model manager
     S3D_CACHE *m_3d_model_manager;
 
+    /// pointer to current color settings
+    COLOR_SETTINGS* m_colors;
 
     // Render options
 
diff --git a/3d-viewer/3d_canvas/eda_3d_canvas.cpp b/3d-viewer/3d_canvas/eda_3d_canvas.cpp
index 34e6da9676..696bd39ebd 100644
--- a/3d-viewer/3d_canvas/eda_3d_canvas.cpp
+++ b/3d-viewer/3d_canvas/eda_3d_canvas.cpp
@@ -44,6 +44,8 @@
 #include <bitmaps.h>
 #include <hotkeys_basic.h>
 #include <menus_helpers.h>
+#include <pgm_base.h>
+#include <settings/settings_manager.h>
 
 #include <widgets/wx_busy_indicator.h>
 
@@ -153,6 +155,8 @@ EDA_3D_CANVAS::EDA_3D_CANVAS( wxWindow *aParent,
     wxASSERT( aBoard != NULL );
     m_settings.SetBoard( aBoard );
 
+    m_settings.SetColorSettings( Pgm().GetSettingsManager().GetColorSettings() );
+
     wxASSERT( a3DCachePointer != NULL );
     m_settings.Set3DCacheManager( a3DCachePointer );
 }
@@ -285,6 +289,8 @@ void EDA_3D_CANVAS::ReloadRequest( BOARD *aBoard , S3D_CACHE *aCachePointer )
     if( aBoard != NULL )
         m_settings.SetBoard( aBoard );
 
+    m_settings.SetColorSettings( Pgm().GetSettingsManager().GetColorSettings() );
+
     if( m_3d_render )
         m_3d_render->ReloadRequest();
 }
diff --git a/3d-viewer/3d_viewer/3d_viewer_settings.cpp b/3d-viewer/3d_viewer/3d_viewer_settings.cpp
new file mode 100644
index 0000000000..739a163564
--- /dev/null
+++ b/3d-viewer/3d_viewer/3d_viewer_settings.cpp
@@ -0,0 +1,157 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 <3d_enums.h>
+#include <settings/common_settings.h>
+#include <settings/parameters.h>
+#include <settings/settings_manager.h>
+#include <wx/config.h>
+
+#include "3d_viewer_settings.h"
+
+///! Update the schema version whenever a migration is required
+const int viewer3dSchemaVersion = 0;
+
+
+EDA_3D_VIEWER_SETTINGS::EDA_3D_VIEWER_SETTINGS() :
+        APP_SETTINGS_BASE( "3d_viewer", viewer3dSchemaVersion ), m_Render()
+{
+    m_params.emplace_back( new PARAM<int>( "render.engine", &m_Render.engine,
+            static_cast<int>( RENDER_ENGINE::OPENGL_LEGACY ),
+            static_cast<int>( RENDER_ENGINE::OPENGL_LEGACY ),
+            static_cast<int>( RENDER_ENGINE::RAYTRACING ) ) );
+
+    m_params.emplace_back( new PARAM<int>( "render.grid_type", &m_Render.grid_type,
+            static_cast<int>( GRID3D_TYPE::NONE ),
+            static_cast<int>( GRID3D_TYPE::NONE ),
+            static_cast<int>( GRID3D_TYPE::GRID_10MM ) ) );
+
+    m_params.emplace_back( new PARAM<int>( "render.material_mode", &m_Render.material_mode,
+            static_cast<int>( MATERIAL_MODE::NORMAL ),
+            static_cast<int>( MATERIAL_MODE::NORMAL ),
+            static_cast<int>( MATERIAL_MODE::CAD_MODE ) ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "render.opengl_copper_thickness", &m_Render.opengl_copper_thickness, true ) );
+    m_params.emplace_back( new PARAM<bool>(
+            "render.opengl_show_model_bbox", &m_Render.opengl_show_model_bbox, false ) );
+    m_params.emplace_back( new PARAM<bool>( "render.raytrace_anti_aliasing",
+            &m_Render.raytrace_anti_aliasing, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.raytrace_backfloor",
+            &m_Render.raytrace_backfloor, false ) );
+    m_params.emplace_back( new PARAM<bool>( "render.raytrace_post_processing",
+            &m_Render.raytrace_post_processing, true ) );
+    m_params.emplace_back(  new PARAM<bool>( "render.raytrace_procedural_textures",
+            &m_Render.raytrace_procedural_textures, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.raytrace_reflections",
+            &m_Render.raytrace_reflections, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.raytrace_refractions",
+            &m_Render.raytrace_refractions, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.raytrace_shadows",
+            &m_Render.raytrace_shadows, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.realistic", &m_Render.realistic, true ) );
+    m_params.emplace_back(
+            new PARAM<bool>( "render.show_adhesive", &m_Render.show_adhesive, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.show_axis", &m_Render.show_axis, true ) );
+    m_params.emplace_back(
+            new PARAM<bool>( "render.show_board_body", &m_Render.show_board_body, true ) );
+    m_params.emplace_back(
+            new PARAM<bool>( "render.show_comments", &m_Render.show_comments, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.show_eco", &m_Render.show_eco, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.show_footprints_insert",
+            &m_Render.show_footprints_insert, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.show_footprints_normal",
+            &m_Render.show_footprints_normal, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.show_footprints_virtual",
+            &m_Render.show_footprints_virtual, true ) );
+    m_params.emplace_back(
+            new PARAM<bool>( "render.show_silkscreen", &m_Render.show_silkscreen, true ) );
+    m_params.emplace_back(
+            new PARAM<bool>( "render.show_soldermask", &m_Render.show_soldermask, true ) );
+    m_params.emplace_back(
+            new PARAM<bool>( "render.show_solderpaste", &m_Render.show_solderpaste, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.show_zones", &m_Render.show_zones, true ) );
+    m_params.emplace_back( new PARAM<bool>( "render.subtract_mask_from_silk",
+            &m_Render.subtract_mask_from_silk, false ) );
+}
+
+
+bool EDA_3D_VIEWER_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacy<int>( aCfg, "RenderEngine",       "render.engine" );
+    ret &= fromLegacy<int>( aCfg, "ShowGrid3D",         "render.grid_type" );
+    ret &= fromLegacy<int>( aCfg, "Render_Material",    "render.material_mode" );
+    ret &= fromLegacy<bool>(
+            aCfg, "Render_OGL_ShowCopperThickness",     "render.opengl_copper_thickness" );
+    ret &= fromLegacy<bool>(
+            aCfg, "Render_OGL_ShowModelBoudingBoxes", "render.opengl_show_model_bbox" );
+    ret &= fromLegacy<bool>( aCfg, "Render_RAY_AntiAliasing",   "render.raytrace_anti_aliasing" );
+    ret &= fromLegacy<bool>( aCfg, "Render_RAY_Backfloor",      "render.raytrace_backfloor" );
+    ret &= fromLegacy<bool>( aCfg, "Render_RAY_PostProcess",    "render.raytrace_post_processing" );
+    ret &= fromLegacy<bool>(
+            aCfg, "Render_RAY_ProceduralTextures", "render.raytrace_procedural_textures" );
+    ret &= fromLegacy<bool>( aCfg, "Render_RAY_Reflections",    "render.raytrace_reflections" );
+    ret &= fromLegacy<bool>( aCfg, "Render_RAY_Refractions",    "render.raytrace_refractions" );
+    ret &= fromLegacy<bool>( aCfg, "Render_RAY_Shadows",        "render.raytrace_shadows" );
+    ret &= fromLegacy<bool>( aCfg, "ShowRealisticMode",         "render.realistic" );
+    ret &= fromLegacy<bool>( aCfg, "ShowAdhesiveLayers",        "render.show_adhesive" );
+    ret &= fromLegacy<bool>( aCfg, "ShowAxis",                  "render.show_axis" );
+    ret &= fromLegacy<bool>( aCfg, "ShowBoardBody",             "render.show_board_body" );
+    ret &= fromLegacy<bool>( aCfg, "ShowCommentsLayers",        "render.show_comments" );
+    ret &= fromLegacy<bool>( aCfg, "ShowEcoLayers",             "render.show_eco" );
+    ret &= fromLegacy<bool>( aCfg, "ShowFootprints_Insert",     "render.show_footprints_insert" );
+    ret &= fromLegacy<bool>( aCfg, "ShowFootprints_Normal",     "render.show_footprints_normal" );
+    ret &= fromLegacy<bool>( aCfg, "ShowFootprints_Virtual",    "render.show_footprints_virtual" );
+    ret &= fromLegacy<bool>( aCfg, "ShowSilkScreenLayers",      "render.show_silkscreen" );
+    ret &= fromLegacy<bool>( aCfg, "ShowSolderMasLayers",       "render.show_soldermask" );
+    ret &= fromLegacy<bool>( aCfg, "ShowSolderPasteLayers",     "render.show_solderpaste" );
+    ret &= fromLegacy<bool>( aCfg, "ShowZones",                 "render.show_zones" );
+    ret &= fromLegacy<bool>( aCfg, "SubtractMaskFromSilk",      "render.subtract_mask_from_silk" );
+
+    auto migrate_color =
+            [&] ( const std::string& k_r, const std::string& k_g,
+                  const std::string &k_b, std::string dest )
+            {
+                COLOR4D color( 1, 1, 1, 1 );
+
+                if( aCfg->Read( k_r, &color.r ) &&
+                    aCfg->Read( k_g, &color.g ) && aCfg->Read( k_b, &color.b ) )
+                {
+                    ( *this )[PointerFromString( dest )] = color;
+                }
+            };
+
+    migrate_color( "BgColor_Red", "BgColor_Green", "BgColor_Blue", "colors.background_bottom" );
+    migrate_color(
+            "BgColor_Red_Top", "BgColor_Green_Top", "BgColor_Blue_Top", "colors.background_top" );
+    migrate_color(
+            "BoardBodyColor_Red", "BoardBodyColor_Green", "BoardBodyColor_Blue", "colors.board" );
+    migrate_color( "CopperColor_Red", "CopperColor_Green", "CopperColor_Blue", "colors.copper" );
+    migrate_color(
+            "SilkColor_Red", "SilkColor_Green", "SilkColor_Blue", "colors.silkscreen_bottom" );
+    migrate_color( "SilkColor_Red", "SilkColor_Green", "SilkColor_Blue", "colors.silkscreen_top" );
+    migrate_color( "SMaskColor_Red", "SMaskColor_Green", "SMaskColor_Blue", "colors.soldermask" );
+    migrate_color(
+            "SPasteColor_Red", "SPasteColor_Green", "SPasteColor_Blue", "colors.solderpaste" );
+
+    return ret;
+}
\ No newline at end of file
diff --git a/3d-viewer/3d_viewer/3d_viewer_settings.h b/3d-viewer/3d_viewer/3d_viewer_settings.h
new file mode 100644
index 0000000000..a7126aa2fa
--- /dev/null
+++ b/3d-viewer/3d_viewer/3d_viewer_settings.h
@@ -0,0 +1,122 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 EDA_3D_VIEWER_SETTINGS_H_
+#define EDA_3D_VIEWER_SETTINGS_H_
+
+#include <settings/app_settings.h>
+#include <settings/parameters.h>
+
+
+class EDA_3D_VIEWER_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+    struct RENDER_SETTINGS
+    {
+        int  engine;
+        int  grid_type;
+        int  material_mode;
+        bool opengl_copper_thickness;
+        bool opengl_show_model_bbox;
+        bool raytrace_anti_aliasing;
+        bool raytrace_backfloor;
+        bool raytrace_post_processing;
+        bool raytrace_procedural_textures;
+        bool raytrace_reflections;
+        bool raytrace_refractions;
+        bool raytrace_shadows;
+        bool realistic;
+        bool show_adhesive;
+        bool show_axis;
+        bool show_board_body;
+        bool show_comments;
+        bool show_eco;
+        bool show_footprints_insert;
+        bool show_footprints_normal;
+        bool show_footprints_virtual;
+        bool show_silkscreen;
+        bool show_soldermask;
+        bool show_solderpaste;
+        bool show_zones;
+        bool subtract_mask_from_silk;
+    };
+
+    EDA_3D_VIEWER_SETTINGS();
+
+    virtual ~EDA_3D_VIEWER_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    RENDER_SETTINGS m_Render;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "Viewer3DFrameName"; }
+};
+
+
+// Individual color param: not necessary once 3D viewer is migrated to color theme system
+// TODO(JE) remove once irrelevant
+class PARAM_COLOR : public PARAM_BASE
+{
+public:
+    PARAM_COLOR( const std::string& aJsonPath, COLOR4D* aPtr, COLOR4D aDefault,
+           bool aReadOnly = false ) :
+            PARAM_BASE( aJsonPath, aReadOnly ), m_ptr( aPtr ), m_default( aDefault )
+    {}
+
+    void Load( JSON_SETTINGS* aSettings ) const override
+    {
+        if( m_readOnly )
+            return;
+
+        COLOR4D val = m_default;
+
+        try
+        {
+            val = aSettings->Get<COLOR4D>( m_path );
+        }
+        catch( ... )
+        {}
+
+        *m_ptr = val;
+    }
+
+    void Store( JSON_SETTINGS* aSettings) const override
+    {
+        aSettings->Set<COLOR4D>( m_path, *m_ptr );
+    }
+
+    COLOR4D GetDefault() const
+    {
+        return m_default;
+    }
+
+    virtual void SetDefault() override
+    {
+        *m_ptr = m_default;
+    }
+
+private:
+    COLOR4D* m_ptr;
+    COLOR4D m_default;
+};
+
+#endif
diff --git a/3d-viewer/3d_viewer/eda_3d_viewer.cpp b/3d-viewer/3d_viewer/eda_3d_viewer.cpp
index cd438bb75b..7a54be41b7 100644
--- a/3d-viewer/3d_viewer/eda_3d_viewer.cpp
+++ b/3d-viewer/3d_viewer/eda_3d_viewer.cpp
@@ -23,7 +23,7 @@
  */
 
 #include "eda_3d_viewer.h"
-
+#include "3d_viewer_settings.h"
 
 #include "../3d_viewer_id.h"
 #include "../common_ogl/cogl_att_list.h"
@@ -35,8 +35,11 @@
 #include <dpi_scaling.h>
 #include <gestfich.h>
 #include <hotkeys_basic.h>
+#include <layers_id_colors_and_visibility.h>
 #include <pgm_base.h>
 #include <project.h>
+#include <settings/common_settings.h>
+#include <settings/settings_manager.h>
 #include <tool/common_control.h>
 #include <tool/tool_manager.h>
 #include <wildcards_and_files_ext.h>
@@ -56,67 +59,6 @@
 const wxChar * EDA_3D_VIEWER::m_logTrace = wxT( "KI_TRACE_EDA_3D_VIEWER" );
 
 
-// Key to store 3D Viewer config
-
-static const wxChar keyBgColor_Red[]            = wxT( "BgColor_Red" );
-static const wxChar keyBgColor_Green[]          = wxT( "BgColor_Green" );
-static const wxChar keyBgColor_Blue[]           = wxT( "BgColor_Blue" );
-
-static const wxChar keyBgColor_Red_Top[]        = wxT( "BgColor_Red_Top" );
-static const wxChar keyBgColor_Green_Top[]      = wxT( "BgColor_Green_Top" );
-static const wxChar keyBgColor_Blue_Top[]       = wxT( "BgColor_Blue_Top" );
-
-static const wxChar keySMaskColor_Red[]         = wxT( "SMaskColor_Red" );
-static const wxChar keySMaskColor_Green[]       = wxT( "SMaskColor_Green" );
-static const wxChar keySMaskColor_Blue[]        = wxT( "SMaskColor_Blue" );
-
-static const wxChar keySPasteColor_Red[]        = wxT( "SPasteColor_Red" );
-static const wxChar keySPasteColor_Green[]      = wxT( "SPasteColor_Green" );
-static const wxChar keySPasteColor_Blue[]       = wxT( "SPasteColor_Blue" );
-
-static const wxChar keySilkColor_Red[]          = wxT( "SilkColor_Red" );
-static const wxChar keySilkColor_Green[]        = wxT( "SilkColor_Green" );
-static const wxChar keySilkColor_Blue[]         = wxT( "SilkColor_Blue" );
-
-static const wxChar keyCopperColor_Red[]        = wxT( "CopperColor_Red" );
-static const wxChar keyCopperColor_Green[]      = wxT( "CopperColor_Green" );
-static const wxChar keyCopperColor_Blue[]       = wxT( "CopperColor_Blue" );
-
-static const wxChar keyBoardBodyColor_Red[]     = wxT( "BoardBodyColor_Red" );
-static const wxChar keyBoardBodyColor_Green[]   = wxT( "BoardBodyColor_Green" );
-static const wxChar keyBoardBodyColor_Blue[]    = wxT( "BoardBodyColor_Blue" );
-
-static const wxChar keyShowRealisticMode[]      = wxT( "ShowRealisticMode" );
-static const wxChar keySubtractMaskFromSilk[]   = wxT( "SubtractMaskFromSilk" );
-static const wxChar keyRenderEngine[]           = wxT( "RenderEngine" );
-static const wxChar keyRenderMaterial[]         = wxT( "Render_Material" );
-
-static const wxChar keyRenderOGL_ShowCopperTck[]= wxT( "Render_OGL_ShowCopperThickness" );
-static const wxChar keyRenderOGL_ShowModelBBox[]= wxT( "Render_OGL_ShowModelBoudingBoxes" );
-
-static const wxChar keyRenderRAY_Shadows[]      = wxT( "Render_RAY_Shadows" );
-static const wxChar keyRenderRAY_Backfloor[]    = wxT( "Render_RAY_Backfloor" );
-static const wxChar keyRenderRAY_Refractions[]  = wxT( "Render_RAY_Refractions" );
-static const wxChar keyRenderRAY_Reflections[]  = wxT( "Render_RAY_Reflections" );
-static const wxChar keyRenderRAY_PostProcess[]  = wxT( "Render_RAY_PostProcess" );
-static const wxChar keyRenderRAY_AAliasing[]    = wxT( "Render_RAY_AntiAliasing" );
-static const wxChar keyRenderRAY_ProceduralT[]  = wxT( "Render_RAY_ProceduralTextures" );
-
-static const wxChar keyShowAxis[]               = wxT( "ShowAxis" );
-static const wxChar keyShowGrid[]               = wxT( "ShowGrid3D" );
-static const wxChar keyShowZones[]              = wxT( "ShowZones" );
-static const wxChar keyShowFootprints_Normal[]  = wxT( "ShowFootprints_Normal" );
-static const wxChar keyShowFootprints_Insert[]  = wxT( "ShowFootprints_Insert" );
-static const wxChar keyShowFootprints_Virtual[] = wxT( "ShowFootprints_Virtual" );
-static const wxChar keyShowAdhesiveLayers[]     = wxT( "ShowAdhesiveLayers" );
-static const wxChar keyShowSilkScreenLayers[]   = wxT( "ShowSilkScreenLayers" );
-static const wxChar keyShowSolderMaskLayers[]   = wxT( "ShowSolderMasLayers" );
-static const wxChar keyShowSolderPasteLayers[]  = wxT( "ShowSolderPasteLayers" );
-static const wxChar keyShowCommentsLayer[]      = wxT( "ShowCommentsLayers" );
-static const wxChar keyShowBoardBody[]          = wxT( "ShowBoardBody" );
-static const wxChar keyShowEcoLayers[]          = wxT( "ShowEcoLayers" );
-
-
 BEGIN_EVENT_TABLE( EDA_3D_VIEWER, EDA_BASE_FRAME )
 
     EVT_ACTIVATE( EDA_3D_VIEWER::OnActivate )
@@ -163,7 +105,8 @@ EDA_3D_VIEWER::EDA_3D_VIEWER( KIWAY *aKiway, PCB_BASE_FRAME *aParent,
     icon.CopyFromBitmap( KiBitmap( icon_3d_xpm ) );
     SetIcon( icon );
 
-    LoadSettings( config() );
+    auto config = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
+    LoadSettings( config );
     SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
 
     // Create the status line
@@ -265,6 +208,9 @@ void EDA_3D_VIEWER::OnCloseWindow( wxCloseEvent &event )
     //delete m_canvas;
     //m_canvas = nullptr;
 
+    COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings();
+    Pgm().GetSettingsManager().SaveColorSettings( colors, "3d_viewer" );
+
     Destroy();
     event.Skip( true );
 }
@@ -553,10 +499,9 @@ void EDA_3D_VIEWER::Process_Special_Functions( wxCommandEvent &event )
 
     case ID_MENU3D_RESET_DEFAULTS:
     {
-        // Reload settings with a dummy config, so it will load the defaults
-        wxConfig *fooconfig = new wxConfig( "FooBarApp" );
-        LoadSettings( fooconfig );
-        delete fooconfig;
+        auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
+        cfg->ResetToDefaults();
+        LoadSettings( cfg );
 
         // Tell canvas that we (may have) changed the render engine
         RenderEngineChanged();
@@ -703,228 +648,152 @@ void EDA_3D_VIEWER::OnSetFocus(wxFocusEvent &event)
 }
 
 
-void EDA_3D_VIEWER::LoadSettings( wxConfigBase *aCfg )
+void EDA_3D_VIEWER::LoadSettings( APP_SETTINGS_BASE *aCfg )
 {
     EDA_BASE_FRAME::LoadSettings( aCfg );
 
+    auto cfg = dynamic_cast<EDA_3D_VIEWER_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+
     wxLogTrace( m_logTrace, "EDA_3D_VIEWER::LoadSettings" );
 
-    aCfg->Read( keyBgColor_Red, &m_settings.m_BgColorBot.r, 0.4 );
-    aCfg->Read( keyBgColor_Green, &m_settings.m_BgColorBot.g, 0.4 );
-    aCfg->Read( keyBgColor_Blue, &m_settings.m_BgColorBot.b, 0.5 );
+    COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings();
 
-    aCfg->Read( keyBgColor_Red_Top, &m_settings.m_BgColorTop.r, 0.8 );
-    aCfg->Read( keyBgColor_Green_Top, &m_settings.m_BgColorTop.g, 0.8 );
-    aCfg->Read( keyBgColor_Blue_Top, &m_settings.m_BgColorTop.b, 0.9 );
+    auto set_color = [] ( const COLOR4D& aColor, SFVEC3D& aTarget )
+    {
+        aTarget.r = aColor.r;
+        aTarget.g = aColor.g;
+        aTarget.b = aColor.b;
+    };
 
-    // m_SolderMaskColorTop default value = dark grey-green
-    aCfg->Read( keySMaskColor_Red, &m_settings.m_SolderMaskColorTop.r, 100.0 * 0.2 / 255.0 );
-    aCfg->Read( keySMaskColor_Green, &m_settings.m_SolderMaskColorTop.g, 255.0 * 0.2 / 255.0 );
-    aCfg->Read( keySMaskColor_Blue, &m_settings.m_SolderMaskColorTop.b, 180.0 * 0.2 / 255.0 );
+    set_color( colors->GetColor( LAYER_3D_BACKGROUND_BOTTOM ), m_settings.m_BgColorBot );
+    set_color( colors->GetColor( LAYER_3D_BACKGROUND_TOP ),    m_settings.m_BgColorTop );
+    set_color( colors->GetColor( LAYER_3D_BOARD ),             m_settings.m_BoardBodyColor );
+    set_color( colors->GetColor( LAYER_3D_COPPER ),            m_settings.m_CopperColor );
+    set_color( colors->GetColor( LAYER_3D_SILKSCREEN_BOTTOM ), m_settings.m_SilkScreenColorBot );
+    set_color( colors->GetColor( LAYER_3D_SILKSCREEN_TOP ),    m_settings.m_SilkScreenColorTop );
+    set_color( colors->GetColor( LAYER_3D_SOLDERMASK ),        m_settings.m_SolderMaskColorBot );
+    set_color( colors->GetColor( LAYER_3D_SOLDERMASK ),        m_settings.m_SolderMaskColorTop );
+    set_color( colors->GetColor( LAYER_3D_SOLDERPASTE ),       m_settings.m_SolderPasteColor );
 
-    // m_SolderMaskColorBot default value = dark grey-green
-    aCfg->Read( keySMaskColor_Red, &m_settings.m_SolderMaskColorBot.r, 100.0 * 0.2 / 255.0 );
-    aCfg->Read( keySMaskColor_Green, &m_settings.m_SolderMaskColorBot.g, 255.0 * 0.2 / 255.0 );
-    aCfg->Read( keySMaskColor_Blue, &m_settings.m_SolderMaskColorBot.b, 180.0 * 0.2 / 255.0 );
+    m_settings.SetFlag( FL_USE_REALISTIC_MODE, cfg->m_Render.realistic );
 
-    // m_SolderPasteColor default value = light grey
-    aCfg->Read( keySPasteColor_Red, &m_settings.m_SolderPasteColor.r, 128.0 / 255.0 );
-    aCfg->Read( keySPasteColor_Green, &m_settings.m_SolderPasteColor.g, 128.0 / 255.0 );
-    aCfg->Read( keySPasteColor_Blue, &m_settings.m_SolderPasteColor.b, 128.0 / 255.0 );
-
-    // m_SilkScreenColorTop default value = white
-    aCfg->Read( keySilkColor_Red, &m_settings.m_SilkScreenColorTop.r, 0.9 );
-    aCfg->Read( keySilkColor_Green, &m_settings.m_SilkScreenColorTop.g, 0.9 );
-    aCfg->Read( keySilkColor_Blue, &m_settings.m_SilkScreenColorTop.b, 0.9 );
-
-    // m_SilkScreenColorBot default value = white
-    aCfg->Read( keySilkColor_Red, &m_settings.m_SilkScreenColorBot.r, 0.9 );
-    aCfg->Read( keySilkColor_Green, &m_settings.m_SilkScreenColorBot.g, 0.9 );
-    aCfg->Read( keySilkColor_Blue, &m_settings.m_SilkScreenColorBot.b, 0.9 );
-
-    // m_CopperColor default value = gold
-    aCfg->Read( keyCopperColor_Red, &m_settings.m_CopperColor.r, 255.0 * 0.7 / 255.0 );
-    aCfg->Read( keyCopperColor_Green, &m_settings.m_CopperColor.g, 223.0 * 0.7 / 255.0 );
-    aCfg->Read( keyCopperColor_Blue, &m_settings.m_CopperColor.b, 0.0 );
-
-    // m_BoardBodyColor default value = FR4, in realistic mode
-    aCfg->Read( keyBoardBodyColor_Red, &m_settings.m_BoardBodyColor.r, 51.0 / 255.0 );
-    aCfg->Read( keyBoardBodyColor_Green, &m_settings.m_BoardBodyColor.g, 43.0 / 255.0 );
-    aCfg->Read( keyBoardBodyColor_Blue, &m_settings.m_BoardBodyColor.b, 22.0 / 255.0 );
-
-
-    bool tmp;
-    aCfg->Read( keyShowRealisticMode, &tmp, true );
-    m_settings.SetFlag( FL_USE_REALISTIC_MODE, tmp );
-
-    aCfg->Read( keySubtractMaskFromSilk, &tmp, false );
-    m_settings.SetFlag( FL_SUBTRACT_MASK_FROM_SILK, tmp );
+    m_settings.SetFlag( FL_SUBTRACT_MASK_FROM_SILK, cfg->m_Render.subtract_mask_from_silk );
 
     // OpenGL options
-    aCfg->Read( keyRenderOGL_ShowCopperTck, &tmp, true );
-    m_settings.SetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS, tmp );
+    m_settings.SetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS,  cfg->m_Render.opengl_copper_thickness );
 
-    aCfg->Read( keyRenderOGL_ShowModelBBox, &tmp, false );
-    m_settings.SetFlag( FL_RENDER_OPENGL_SHOW_MODEL_BBOX, tmp );
+    m_settings.SetFlag( FL_RENDER_OPENGL_SHOW_MODEL_BBOX,   cfg->m_Render.opengl_show_model_bbox );
 
     // Raytracing options
-    aCfg->Read( keyRenderRAY_Shadows, &tmp, true );
-    m_settings.SetFlag( FL_RENDER_RAYTRACING_SHADOWS, tmp );
+    m_settings.SetFlag( FL_RENDER_RAYTRACING_SHADOWS,       cfg->m_Render.raytrace_shadows );
 
-    aCfg->Read( keyRenderRAY_Backfloor, &tmp, false );
-    m_settings.SetFlag( FL_RENDER_RAYTRACING_BACKFLOOR, tmp );
+    m_settings.SetFlag( FL_RENDER_RAYTRACING_BACKFLOOR,     cfg->m_Render.raytrace_backfloor );
 
-    aCfg->Read( keyRenderRAY_Refractions, &tmp, true );
-    m_settings.SetFlag( FL_RENDER_RAYTRACING_REFRACTIONS, tmp );
+    m_settings.SetFlag( FL_RENDER_RAYTRACING_REFRACTIONS,   cfg->m_Render.raytrace_refractions );
 
-    aCfg->Read( keyRenderRAY_Reflections, &tmp, true );
-    m_settings.SetFlag( FL_RENDER_RAYTRACING_REFLECTIONS, tmp );
+    m_settings.SetFlag( FL_RENDER_RAYTRACING_REFLECTIONS,   cfg->m_Render.raytrace_reflections );
 
-    aCfg->Read( keyRenderRAY_PostProcess, &tmp, true );
-    m_settings.SetFlag( FL_RENDER_RAYTRACING_POST_PROCESSING, tmp );
+    m_settings.SetFlag( FL_RENDER_RAYTRACING_POST_PROCESSING,
+            cfg->m_Render.raytrace_post_processing );
 
-    aCfg->Read( keyRenderRAY_AAliasing, &tmp, true );
-    m_settings.SetFlag( FL_RENDER_RAYTRACING_ANTI_ALIASING, tmp );
+    m_settings.SetFlag( FL_RENDER_RAYTRACING_ANTI_ALIASING, cfg->m_Render.raytrace_anti_aliasing );
 
-    aCfg->Read( keyRenderRAY_ProceduralT, &tmp, true );
-    m_settings.SetFlag( FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES, tmp );
+    m_settings.SetFlag( FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES,
+            cfg->m_Render.raytrace_procedural_textures );
 
-    aCfg->Read( keyShowAxis, &tmp, true );
-    m_settings.SetFlag( FL_AXIS, tmp );
+    m_settings.SetFlag( FL_AXIS, cfg->m_Render.show_axis );
 
-    aCfg->Read( keyShowFootprints_Normal, &tmp, true );
-    m_settings.SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, tmp );
+    m_settings.SetFlag( FL_MODULE_ATTRIBUTES_NORMAL, cfg->m_Render.show_footprints_normal );
 
-    aCfg->Read( keyShowFootprints_Insert, &tmp, true );
-    m_settings.SetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT, tmp );
+    m_settings.SetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT, cfg->m_Render.show_footprints_insert );
 
-    aCfg->Read( keyShowFootprints_Virtual, &tmp, true );
-    m_settings.SetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL, tmp );
+    m_settings.SetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL, cfg->m_Render.show_footprints_virtual );
 
-    aCfg->Read( keyShowZones, &tmp, true );
-    m_settings.SetFlag( FL_ZONE, tmp );
+    m_settings.SetFlag( FL_ZONE, cfg->m_Render.show_zones );
 
-    aCfg->Read( keyShowAdhesiveLayers, &tmp, true );
-    m_settings.SetFlag( FL_ADHESIVE, tmp );
+    m_settings.SetFlag( FL_ADHESIVE, cfg->m_Render.show_adhesive );
 
-    aCfg->Read( keyShowSilkScreenLayers, &tmp, true );
-    m_settings.SetFlag( FL_SILKSCREEN, tmp );
+    m_settings.SetFlag( FL_SILKSCREEN, cfg->m_Render.show_silkscreen );
 
-    aCfg->Read( keyShowSolderMaskLayers, &tmp, true );
-    m_settings.SetFlag( FL_SOLDERMASK, tmp );
+    m_settings.SetFlag( FL_SOLDERMASK, cfg->m_Render.show_soldermask );
 
-    aCfg->Read( keyShowSolderPasteLayers, &tmp, true );
-    m_settings.SetFlag( FL_SOLDERPASTE, tmp );
+    m_settings.SetFlag( FL_SOLDERPASTE, cfg->m_Render.show_solderpaste );
 
-    aCfg->Read( keyShowCommentsLayer, &tmp, true );
-    m_settings.SetFlag( FL_COMMENTS, tmp );
+    m_settings.SetFlag( FL_COMMENTS, cfg->m_Render.show_comments );
 
-    aCfg->Read( keyShowEcoLayers, &tmp, true );
-    m_settings.SetFlag( FL_ECO, tmp );
+    m_settings.SetFlag( FL_ECO, cfg->m_Render.show_eco );
 
-    aCfg->Read( keyShowBoardBody, &tmp, true );
-    m_settings.SetFlag( FL_SHOW_BOARD_BODY, tmp );
+    m_settings.SetFlag( FL_SHOW_BOARD_BODY, cfg->m_Render.show_board_body );
 
-    int tmpi;
-    aCfg->Read( keyShowGrid, &tmpi, static_cast<int>( GRID3D_TYPE::NONE ) );
-    m_settings.GridSet( static_cast<GRID3D_TYPE>( tmpi ) );
+    m_settings.GridSet( static_cast<GRID3D_TYPE>( cfg->m_Render.grid_type ) );
 
-    aCfg->Read( keyRenderEngine, &tmpi, static_cast<int>( RENDER_ENGINE::OPENGL_LEGACY ) );
+    RENDER_ENGINE engine = static_cast<RENDER_ENGINE>( cfg->m_Render.engine );
     wxLogTrace( m_logTrace, "EDA_3D_VIEWER::LoadSettings render setting %s",
-            ( static_cast<RENDER_ENGINE>( tmpi ) == RENDER_ENGINE::RAYTRACING ) ? "Ray Trace" :
-                                                                                  "OpenGL" );
-    m_settings.RenderEngineSet( static_cast<RENDER_ENGINE>( tmpi ) );
+            ( engine == RENDER_ENGINE::RAYTRACING ) ? "Ray Trace" : "OpenGL" );
+    m_settings.RenderEngineSet( engine );
 
-    aCfg->Read( keyRenderMaterial, &tmpi, static_cast<int>( MATERIAL_MODE::NORMAL ) );
-    m_settings.MaterialModeSet( static_cast<MATERIAL_MODE>( tmpi ) );
+    m_settings.MaterialModeSet( static_cast<MATERIAL_MODE>( cfg->m_Render.material_mode ) );
 }
 
 
-void EDA_3D_VIEWER::SaveSettings( wxConfigBase *aCfg )
+void EDA_3D_VIEWER::SaveSettings( APP_SETTINGS_BASE *aCfg )
 {
-    EDA_BASE_FRAME::SaveSettings( aCfg );
+    auto cfg = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>();
+
+    EDA_BASE_FRAME::SaveSettings( cfg );
 
     wxLogTrace( m_logTrace, "EDA_3D_VIEWER::SaveSettings" );
 
-    aCfg->Write( keyBgColor_Red, m_settings.m_BgColorBot.r );
-    aCfg->Write( keyBgColor_Green, m_settings.m_BgColorBot.g );
-    aCfg->Write( keyBgColor_Blue, m_settings.m_BgColorBot.b );
+    COLOR_SETTINGS* colors = Pgm().GetSettingsManager().GetColorSettings();
 
-    aCfg->Write( keyBgColor_Red_Top, m_settings.m_BgColorTop.r );
-    aCfg->Write( keyBgColor_Green_Top, m_settings.m_BgColorTop.g );
-    aCfg->Write( keyBgColor_Blue_Top, m_settings.m_BgColorTop.b );
+    auto save_color = [colors] ( SFVEC3D& aSource, LAYER_3D_ID aTarget )
+    {
+        colors->SetColor( aTarget, COLOR4D( aSource.r, aSource.g, aSource.b, 1.0 ) );
+    };
 
-    aCfg->Write( keySMaskColor_Red, m_settings.m_SolderMaskColorTop.r );
-    aCfg->Write( keySMaskColor_Green, m_settings.m_SolderMaskColorTop.g );
-    aCfg->Write( keySMaskColor_Blue, m_settings.m_SolderMaskColorTop.b );
+    save_color( m_settings.m_BgColorBot,         LAYER_3D_BACKGROUND_BOTTOM );
+    save_color( m_settings.m_BgColorTop,         LAYER_3D_BACKGROUND_TOP );
+    save_color( m_settings.m_BoardBodyColor,     LAYER_3D_BOARD );
+    save_color( m_settings.m_CopperColor,        LAYER_3D_COPPER );
+    save_color( m_settings.m_SilkScreenColorBot, LAYER_3D_SILKSCREEN_BOTTOM );
+    save_color( m_settings.m_SilkScreenColorTop, LAYER_3D_SILKSCREEN_TOP );
+    save_color( m_settings.m_SolderMaskColorTop, LAYER_3D_SOLDERMASK );
+    save_color( m_settings.m_SolderPasteColor,   LAYER_3D_SOLDERPASTE );
 
-    aCfg->Write( keySMaskColor_Red, m_settings.m_SolderMaskColorBot.r );
-    aCfg->Write( keySMaskColor_Green, m_settings.m_SolderMaskColorBot.g );
-    aCfg->Write( keySMaskColor_Blue, m_settings.m_SolderMaskColorBot.b );
-
-    aCfg->Write( keySPasteColor_Red, m_settings.m_SolderPasteColor.r );
-    aCfg->Write( keySPasteColor_Green, m_settings.m_SolderPasteColor.g );
-    aCfg->Write( keySPasteColor_Blue, m_settings.m_SolderPasteColor.b );
-
-    aCfg->Write( keySilkColor_Red, m_settings.m_SilkScreenColorTop.r );
-    aCfg->Write( keySilkColor_Green, m_settings.m_SilkScreenColorTop.g );
-    aCfg->Write( keySilkColor_Blue, m_settings.m_SilkScreenColorTop.b );
-
-    aCfg->Write( keySilkColor_Red, m_settings.m_SilkScreenColorBot.r );
-    aCfg->Write( keySilkColor_Green, m_settings.m_SilkScreenColorBot.g );
-    aCfg->Write( keySilkColor_Blue, m_settings.m_SilkScreenColorBot.b );
-
-    aCfg->Write( keyCopperColor_Red, m_settings.m_CopperColor.r );
-    aCfg->Write( keyCopperColor_Green, m_settings.m_CopperColor.g );
-    aCfg->Write( keyCopperColor_Blue, m_settings.m_CopperColor.b );
-
-    aCfg->Write( keyBoardBodyColor_Red, m_settings.m_BoardBodyColor.r );
-    aCfg->Write( keyBoardBodyColor_Green, m_settings.m_BoardBodyColor.g );
-    aCfg->Write( keyBoardBodyColor_Blue, m_settings.m_BoardBodyColor.b );
-
-    aCfg->Write( keyShowRealisticMode, m_settings.GetFlag( FL_USE_REALISTIC_MODE ) );
-    aCfg->Write( keySubtractMaskFromSilk, m_settings.GetFlag( FL_SUBTRACT_MASK_FROM_SILK ) );
-
-    aCfg->Write( keyRenderEngine, static_cast<int>( m_settings.RenderEngineGet() ) );
     wxLogTrace( m_logTrace, "EDA_3D_VIEWER::SaveSettings render setting %s",
             ( m_settings.RenderEngineGet() == RENDER_ENGINE::RAYTRACING ) ? "Ray Trace" :
                                                                             "OpenGL" );
 
-    aCfg->Write( keyRenderMaterial, (int) m_settings.MaterialModeGet() );
+    cfg->m_Render.engine        = static_cast<int>( m_settings.RenderEngineGet() );
+    cfg->m_Render.grid_type     = static_cast<int>( m_settings.GridGet() );
+    cfg->m_Render.material_mode = static_cast<int>( m_settings.MaterialModeGet() );
 
-    // OpenGL options
-    aCfg->Write( keyRenderOGL_ShowCopperTck,
-                 m_settings.GetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS ) );
-    aCfg->Write( keyRenderOGL_ShowModelBBox,
-                 m_settings.GetFlag( FL_RENDER_OPENGL_SHOW_MODEL_BBOX ) );
-
-    // Raytracing options
-    aCfg->Write( keyRenderRAY_Shadows, m_settings.GetFlag( FL_RENDER_RAYTRACING_SHADOWS ) );
-    aCfg->Write( keyRenderRAY_Backfloor, m_settings.GetFlag( FL_RENDER_RAYTRACING_BACKFLOOR ) );
-    aCfg->Write( keyRenderRAY_Refractions, m_settings.GetFlag( FL_RENDER_RAYTRACING_REFRACTIONS ) );
-    aCfg->Write( keyRenderRAY_Reflections, m_settings.GetFlag( FL_RENDER_RAYTRACING_REFLECTIONS ) );
-    aCfg->Write(
-            keyRenderRAY_PostProcess, m_settings.GetFlag( FL_RENDER_RAYTRACING_POST_PROCESSING ) );
-    aCfg->Write( keyRenderRAY_AAliasing, m_settings.GetFlag( FL_RENDER_RAYTRACING_ANTI_ALIASING ) );
-    aCfg->Write( keyRenderRAY_ProceduralT,
-            m_settings.GetFlag( FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES ) );
-
-    aCfg->Write( keyShowAxis, m_settings.GetFlag( FL_AXIS ) );
-    aCfg->Write( keyShowGrid, (int) m_settings.GridGet() );
-
-    aCfg->Write( keyShowFootprints_Normal, m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL ) );
-    aCfg->Write(
-            keyShowFootprints_Insert, m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT ) );
-    aCfg->Write( keyShowFootprints_Virtual, m_settings.GetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL ) );
-
-    aCfg->Write( keyShowZones, m_settings.GetFlag( FL_ZONE ) );
-    aCfg->Write( keyShowAdhesiveLayers, m_settings.GetFlag( FL_ADHESIVE ) );
-    aCfg->Write( keyShowSilkScreenLayers, m_settings.GetFlag( FL_SILKSCREEN ) );
-    aCfg->Write( keyShowSolderMaskLayers, m_settings.GetFlag( FL_SOLDERMASK ) );
-    aCfg->Write( keyShowSolderPasteLayers, m_settings.GetFlag( FL_SOLDERPASTE ) );
-    aCfg->Write( keyShowCommentsLayer, m_settings.GetFlag( FL_COMMENTS ) );
-    aCfg->Write( keyShowEcoLayers, m_settings.GetFlag( FL_ECO ) );
-    aCfg->Write( keyShowBoardBody, m_settings.GetFlag( FL_SHOW_BOARD_BODY ) );
+    cfg->m_Render.opengl_copper_thickness = m_settings.GetFlag( FL_RENDER_OPENGL_COPPER_THICKNESS );
+    cfg->m_Render.opengl_show_model_bbox = m_settings.GetFlag( FL_RENDER_OPENGL_SHOW_MODEL_BBOX );
+    cfg->m_Render.raytrace_anti_aliasing = m_settings.GetFlag( FL_RENDER_RAYTRACING_ANTI_ALIASING );
+    cfg->m_Render.raytrace_backfloor     = m_settings.GetFlag( FL_RENDER_RAYTRACING_BACKFLOOR );
+    cfg->m_Render.raytrace_post_processing =
+            m_settings.GetFlag( FL_RENDER_RAYTRACING_POST_PROCESSING );
+    cfg->m_Render.raytrace_procedural_textures =
+            m_settings.GetFlag( FL_RENDER_RAYTRACING_PROCEDURAL_TEXTURES );
+    cfg->m_Render.raytrace_reflections    = m_settings.GetFlag( FL_RENDER_RAYTRACING_REFLECTIONS );
+    cfg->m_Render.raytrace_refractions    = m_settings.GetFlag( FL_RENDER_RAYTRACING_REFRACTIONS );
+    cfg->m_Render.raytrace_shadows        = m_settings.GetFlag( FL_RENDER_RAYTRACING_SHADOWS );
+    cfg->m_Render.realistic               = m_settings.GetFlag( FL_USE_REALISTIC_MODE );
+    cfg->m_Render.show_adhesive           = m_settings.GetFlag( FL_ADHESIVE );
+    cfg->m_Render.show_axis               = m_settings.GetFlag( FL_AXIS );
+    cfg->m_Render.show_board_body         = m_settings.GetFlag( FL_SHOW_BOARD_BODY );
+    cfg->m_Render.show_comments           = m_settings.GetFlag( FL_COMMENTS );
+    cfg->m_Render.show_eco                = m_settings.GetFlag( FL_ECO );
+    cfg->m_Render.show_footprints_insert = m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL_INSERT );
+    cfg->m_Render.show_footprints_normal  = m_settings.GetFlag( FL_MODULE_ATTRIBUTES_NORMAL );
+    cfg->m_Render.show_footprints_virtual = m_settings.GetFlag( FL_MODULE_ATTRIBUTES_VIRTUAL );
+    cfg->m_Render.show_silkscreen         = m_settings.GetFlag( FL_SILKSCREEN );
+    cfg->m_Render.show_soldermask         = m_settings.GetFlag( FL_SOLDERMASK );
+    cfg->m_Render.show_solderpaste        = m_settings.GetFlag( FL_SOLDERPASTE );
+    cfg->m_Render.show_zones              = m_settings.GetFlag( FL_ZONE );
+    cfg->m_Render.subtract_mask_from_silk = m_settings.GetFlag( FL_SUBTRACT_MASK_FROM_SILK );
 }
 
 
@@ -1269,16 +1138,9 @@ void EDA_3D_VIEWER::loadCommonSettings()
 {
     wxCHECK_RET( m_canvas, "Cannot load settings to null canvas" );
 
-    wxConfigBase& cmnCfg = *Pgm().CommonSettings();
+    COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
 
-    {
-        const DPI_SCALING dpi{ &cmnCfg, this };
-        m_canvas->SetScaleFactor( dpi.GetScaleFactor() );
-    }
-
-    {
-        bool option;
-        cmnCfg.Read( ENBL_MOUSEWHEEL_PAN_KEY, &option, false );
-        m_settings.SetFlag( FL_MOUSEWHEEL_PANNING, option );
-    }
+    const DPI_SCALING dpi{ settings, this };
+    m_canvas->SetScaleFactor( dpi.GetScaleFactor() );
+    m_settings.SetFlag( FL_MOUSEWHEEL_PANNING, settings->m_Input.mousewheel_pan );
 }
diff --git a/3d-viewer/3d_viewer/eda_3d_viewer.h b/3d-viewer/3d_viewer/eda_3d_viewer.h
index 19aae1c374..c8145bdec3 100644
--- a/3d-viewer/3d_viewer/eda_3d_viewer.h
+++ b/3d-viewer/3d_viewer/eda_3d_viewer.h
@@ -194,9 +194,9 @@ private:
      */
     void ReCreateMainToolbar();
 
-    void SaveSettings( wxConfigBase *aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE *aCfg ) override;
 
-    void LoadSettings( wxConfigBase *aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE *aCfg ) override;
 
     void OnKeyEvent( wxKeyEvent& event );
 
diff --git a/3d-viewer/CMakeLists.txt b/3d-viewer/CMakeLists.txt
index 05a6ace4c6..93ff5d6981 100644
--- a/3d-viewer/CMakeLists.txt
+++ b/3d-viewer/CMakeLists.txt
@@ -94,6 +94,7 @@ set(3D-VIEWER_SRCS
     3d_viewer/dialogs/dialog_3D_view_option.cpp
     3d_viewer/dialogs/dialog_3D_view_option_base.cpp
     3d_viewer/eda_3d_viewer.cpp
+    3d_viewer/3d_viewer_settings.cpp
     common_ogl/cogl_att_list.cpp
     common_ogl/ogl_utils.cpp
     3d_fastmath.cpp
@@ -111,4 +112,8 @@ target_link_libraries( 3d-viewer
                        ${OPENGL_LIBRARIES}
                        kicad_3dsg )
 
+target_include_directories( 3d-viewer PRIVATE
+    $<TARGET_PROPERTY:nlohmann_json,INTERFACE_INCLUDE_DIRECTORIES>
+    )
+
 add_subdirectory( 3d_cache )
diff --git a/bitmap2component/CMakeLists.txt b/bitmap2component/CMakeLists.txt
index 544536935d..86c42ec29b 100644
--- a/bitmap2component/CMakeLists.txt
+++ b/bitmap2component/CMakeLists.txt
@@ -12,6 +12,7 @@ set( BITMAP2COMPONENT_SRCS
     ${CMAKE_SOURCE_DIR}/common/single_top.cpp
 
     bitmap2cmp_main.cpp
+    bitmap2cmp_settings.cpp
     bitmap2component.cpp
     bitmap2cmp_gui_base.cpp
     bitmap2cmp_gui.cpp
diff --git a/bitmap2component/bitmap2cmp_gui.cpp b/bitmap2component/bitmap2cmp_gui.cpp
index 75f87ac047..75078121e1 100644
--- a/bitmap2component/bitmap2cmp_gui.cpp
+++ b/bitmap2component/bitmap2cmp_gui.cpp
@@ -24,6 +24,7 @@
 
 #include "bitmap2cmp_gui.h"
 #include "bitmap2component.h"
+#include <bitmap2cmp_settings.h>
 #include <bitmap_io.h>
 #include <bitmaps.h>
 #include <kiface_i.h>
@@ -38,18 +39,6 @@
 #include "bitmap2cmp_gui_base.h"
 
 
-#define KEYWORD_FRAME_POSX          wxT( "Bmconverter_Pos_x" )
-#define KEYWORD_FRAME_POSY          wxT( "Bmconverter_Pos_y" )
-#define KEYWORD_FRAME_SIZEX         wxT( "Bmconverter_Size_x" )
-#define KEYWORD_FRAME_SIZEY         wxT( "Bmconverter_Size_y" )
-#define KEYWORD_LAST_INPUT_FILE     wxT( "Last_input" )
-#define KEYWORD_LAST_OUTPUT_FILE    wxT( "Last_output" )
-#define KEYWORD_LAST_FORMAT         wxT( "Last_format" )
-#define KEYWORD_LAST_MODLAYER       wxT( "Last_modlayer" )
-#define KEYWORD_BINARY_THRESHOLD    wxT( "Threshold" )
-#define KEYWORD_BW_NEGATIVE         wxT( "Negative_choice" )
-#define KEYWORD_UNIT_SELECTION      wxT( "Unit_selection" )
-
 #define DEFAULT_DPI 300     // the image DPI used in formats that do not define a DPI
 
 IMAGE_SIZE::IMAGE_SIZE()
@@ -161,7 +150,6 @@ BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
     BM2CMP_FRAME_BASE( aParent )
 {
     SetKiway( this, aKiway );
-    m_config = GetNewConfig( Pgm().App().GetAppName() );
 
     wxString unitList[] =
     {
@@ -171,7 +159,7 @@ BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
     for( int ii = 0; ii < 3; ii++ )
         m_PixelUnit->Append( unitList[ii] );
 
-    LoadSettings( m_config.get() );
+    LoadSettings( config() );
 
     m_outputSizeX.SetUnit( getUnitFromSelection() );
     m_outputSizeY.SetUnit( getUnitFromSelection() );
@@ -193,20 +181,19 @@ BM2CMP_FRAME::BM2CMP_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
 
     GetSizer()->SetSizeHints( this );
 
-    SetSize( m_framePos.x, m_framePos.y, m_frameSize.x, m_frameSize.y );
-
     m_buttonExportFile->Enable( false );
     m_buttonExportClipboard->Enable( false );
 
+    SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
 
-    if ( m_framePos == wxDefaultPosition )
+    if ( m_FramePos == wxDefaultPosition )
         Centre();
 }
 
 
 BM2CMP_FRAME::~BM2CMP_FRAME()
 {
-    SaveSettings( m_config.get() );
+    SaveSettings( config() );
     /*
      * This needed for OSX: avoids further OnDraw processing after this
      * destructor and before the native window is destroyed
@@ -215,79 +202,63 @@ BM2CMP_FRAME::~BM2CMP_FRAME()
 }
 
 
-void BM2CMP_FRAME::LoadSettings( wxConfigBase* aCfg )
+void BM2CMP_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
-    int tmp;
-    aCfg->Read( KEYWORD_FRAME_POSX, & m_framePos.x, -1 );
-    aCfg->Read( KEYWORD_FRAME_POSY, & m_framePos.y, -1 );
-    aCfg->Read( KEYWORD_FRAME_SIZEX, & m_frameSize.x, -1 );
-    aCfg->Read( KEYWORD_FRAME_SIZEY, & m_frameSize.y, -1 );
-    aCfg->Read( KEYWORD_LAST_INPUT_FILE, &m_BitmapFileName );
-    aCfg->Read( KEYWORD_LAST_OUTPUT_FILE, &m_ConvertedFileName );
+    EDA_BASE_FRAME::LoadSettings( aCfg );
 
-    int u_select = 0;
-    aCfg->Read( KEYWORD_UNIT_SELECTION, &u_select, 0 );
+    auto cfg = static_cast<BITMAP2CMP_SETTINGS*>( aCfg );
+
+    m_BitmapFileName    = cfg->m_BitmapFileName;
+    m_ConvertedFileName = cfg->m_ConvertedFileName;
+
+    int u_select = cfg->m_Units;
 
     if( u_select < 0 || u_select > 2 )  // Validity control
         u_select = 0;
 
     m_PixelUnit->SetSelection( u_select );
 
-    if( aCfg->Read( KEYWORD_BINARY_THRESHOLD, &tmp ) )
-        m_sliderThreshold->SetValue( tmp );
+    m_sliderThreshold->SetValue( cfg->m_Threshold );
 
-    aCfg->Read( KEYWORD_BW_NEGATIVE, &tmp, 0 );
-    m_Negative = tmp != 0;
-    m_checkNegative->SetValue( m_Negative );
+    m_Negative = cfg->m_Negative;
+    m_checkNegative->SetValue( cfg->m_Negative );
     m_exportToClipboard = false;
     m_AspectRatioLocked = false;
 
-    if( aCfg->Read( KEYWORD_LAST_FORMAT, &tmp ) )
-    {
-        if( tmp < 0 || tmp > FINAL_FMT )
-            tmp = PCBNEW_KICAD_MOD;
+    int format = cfg->m_LastFormat;
 
-        m_rbOutputFormat->SetSelection( tmp );
-    }
+    if( format < 0 || format > FINAL_FMT )
+        format = PCBNEW_KICAD_MOD;
 
-    if( tmp == PCBNEW_KICAD_MOD )
+    m_rbOutputFormat->SetSelection( format );
+
+    if( format == PCBNEW_KICAD_MOD )
         m_rbPCBLayer->Enable( true );
     else
         m_rbPCBLayer->Enable( false );
 
-    if( aCfg->Read( KEYWORD_LAST_MODLAYER, &tmp ) )
-    {
-        if( (unsigned) tmp > MOD_LYR_FINAL )    // Out of range
-            m_rbPCBLayer->SetSelection( MOD_LYR_FSILKS );
-        else
-            m_rbPCBLayer->SetSelection( tmp );
-    }
+    int last_layer = cfg->m_LastModLayer;
+
+    if( last_layer > static_cast<int>( MOD_LYR_FINAL ) )   // Out of range
+        m_rbPCBLayer->SetSelection( MOD_LYR_FSILKS );
+    else
+        m_rbPCBLayer->SetSelection( last_layer );
 }
 
 
-void BM2CMP_FRAME::SaveSettings( wxConfigBase* aCfg )
+void BM2CMP_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
-    if( !aCfg )
-        return;
+    EDA_BASE_FRAME::SaveSettings( aCfg );
 
-    m_frameSize = GetSize();
-    m_framePos  = GetPosition();
+    auto cfg = static_cast<BITMAP2CMP_SETTINGS*>( aCfg );
 
-    if( !IsIconized()  )
-    {
-        aCfg->Write( KEYWORD_FRAME_POSX, (long) m_framePos.x );
-        aCfg->Write( KEYWORD_FRAME_POSY, (long) m_framePos.y );
-        aCfg->Write( KEYWORD_FRAME_SIZEX, (long) m_frameSize.x );
-        aCfg->Write( KEYWORD_FRAME_SIZEY, (long) m_frameSize.y );
-    }
-
-    aCfg->Write( KEYWORD_LAST_INPUT_FILE, m_BitmapFileName );
-    aCfg->Write( KEYWORD_LAST_OUTPUT_FILE, m_ConvertedFileName );
-    aCfg->Write( KEYWORD_BINARY_THRESHOLD, m_sliderThreshold->GetValue() );
-    aCfg->Write( KEYWORD_BW_NEGATIVE, m_checkNegative->IsChecked() ? 1 : 0 );
-    aCfg->Write( KEYWORD_LAST_FORMAT,  m_rbOutputFormat->GetSelection() );
-    aCfg->Write( KEYWORD_LAST_MODLAYER,  m_rbPCBLayer->GetSelection() );
-    aCfg->Write( KEYWORD_UNIT_SELECTION, m_PixelUnit->GetSelection() );
+    cfg->m_BitmapFileName    = m_BitmapFileName;
+    cfg->m_ConvertedFileName = m_ConvertedFileName;
+    cfg->m_Threshold         = m_sliderThreshold->GetValue();
+    cfg->m_Negative          = m_checkNegative->IsChecked();
+    cfg->m_LastFormat        = m_rbOutputFormat->GetSelection();
+    cfg->m_LastModLayer      = m_rbPCBLayer->GetSelection();
+    cfg->m_Units             = m_PixelUnit->GetSelection();
 }
 
 
diff --git a/bitmap2component/bitmap2cmp_gui.h b/bitmap2component/bitmap2cmp_gui.h
index 5225296998..e390761c72 100644
--- a/bitmap2component/bitmap2cmp_gui.h
+++ b/bitmap2component/bitmap2cmp_gui.h
@@ -152,8 +152,8 @@ private:
     void OnFormatChange( wxCommandEvent& event ) override;
     void exportBitmap( OUTPUT_FMT_ID aFormat );
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
 private:
     wxImage  m_Pict_Image;
@@ -167,9 +167,6 @@ private:
     bool                          m_Negative;
     wxString                      m_BitmapFileName;
     wxString                      m_ConvertedFileName;
-    wxSize                        m_frameSize;
-    wxPoint                       m_framePos;
-    std::unique_ptr<wxConfigBase> m_config;
     bool                          m_exportToClipboard;
     bool                          m_AspectRatioLocked;
     double                        m_AspectRatio;
diff --git a/bitmap2component/bitmap2cmp_main.cpp b/bitmap2component/bitmap2cmp_main.cpp
index fb9c1d2eb6..2ff7f23dab 100644
--- a/bitmap2component/bitmap2cmp_main.cpp
+++ b/bitmap2component/bitmap2cmp_main.cpp
@@ -22,10 +22,12 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include "bitmap2cmp_gui.h"
+#include <bitmap2cmp_gui.h>
+#include <bitmap2cmp_settings.h>
 #include <kiface_i.h>
 #include <kiway.h>
 #include <pgm_base.h>
+#include <settings/settings_manager.h>
 
 
 //-----<KIFACE>-----------------------------------------------------------------
@@ -38,6 +40,8 @@ static struct IFACE : public KIFACE_I
 
     wxWindow* CreateWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) override
     {
+        InitSettings( new BITMAP2CMP_SETTINGS );
+        Pgm().GetSettingsManager().RegisterSettings( KifaceSettings() );
         return new BM2CMP_FRAME( aKiway, aParent );
     }
 
diff --git a/bitmap2component/bitmap2cmp_settings.cpp b/bitmap2component/bitmap2cmp_settings.cpp
new file mode 100644
index 0000000000..ab8128880d
--- /dev/null
+++ b/bitmap2component/bitmap2cmp_settings.cpp
@@ -0,0 +1,68 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#include <bitmap2cmp_settings.h>
+#include <settings/parameters.h>
+#include <wx/config.h>
+
+
+///! Update the schema version whenever a migration is required
+const int bitmap2cmpSchemaVersion = 0;
+
+
+BITMAP2CMP_SETTINGS::BITMAP2CMP_SETTINGS() :
+        APP_SETTINGS_BASE( "bitmap2component", bitmap2cmpSchemaVersion ),
+        m_BitmapFileName(), m_ConvertedFileName(), m_Units(), m_Threshold(), m_Negative(),
+        m_LastFormat(), m_LastModLayer()
+{
+    m_params.emplace_back( new PARAM<wxString>( "bitmap_file_name", &m_BitmapFileName, "" ) );
+
+    m_params.emplace_back(
+            new PARAM<wxString>( "converted_file_name", &m_ConvertedFileName, "" ) );
+
+    m_params.emplace_back( new PARAM<int>( "units", &m_Units, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "threshold", &m_Threshold, 50 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "negative", &m_Negative, false ) );
+
+    m_params.emplace_back( new PARAM<int>( "last_format", &m_LastFormat, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "last_mod_layer", &m_LastModLayer, 0 ) );
+}
+
+
+bool BITMAP2CMP_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacyString( aCfg, "Last_input",        "bitmap_file_name" );
+    ret &= fromLegacyString( aCfg, "Last_output",       "converted_file_name" );
+    ret &= fromLegacy<int>(  aCfg, "Last_format",       "last_format" );
+    ret &= fromLegacy<int>(  aCfg, "Last_modlayer",     "last_mod_layer" );
+    ret &= fromLegacy<int>(  aCfg, "Threshold",         "threshold" );
+    ret &= fromLegacy<bool>( aCfg, "Negative_choice",   "negative" );
+    ret &= fromLegacy<int>(  aCfg, "Unit_selection",    "units" );
+
+    return ret;
+}
diff --git a/bitmap2component/bitmap2cmp_settings.h b/bitmap2component/bitmap2cmp_settings.h
new file mode 100644
index 0000000000..d6daa968bf
--- /dev/null
+++ b/bitmap2component/bitmap2cmp_settings.h
@@ -0,0 +1,58 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#ifndef _BITMAP2CMP_SETTINGS_H
+#define _BITMAP2CMP_SETTINGS_H
+
+#include <settings/app_settings.h>
+
+class BITMAP2CMP_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+    BITMAP2CMP_SETTINGS();
+
+    virtual ~BITMAP2CMP_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    wxString m_BitmapFileName;
+
+    wxString m_ConvertedFileName;
+
+    int m_Units;
+
+    int m_Threshold;
+
+    bool m_Negative;
+
+    int m_LastFormat;
+
+    int m_LastModLayer;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "Bmconverter_"; }
+};
+
+
+#endif
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index c61396b0c6..4f8c8deb02 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -82,6 +82,10 @@ target_link_libraries( gal
     ${GDI_PLUS_LIBRARIES}
 )
 
+target_include_directories( gal PRIVATE
+    $<TARGET_PROPERTY:nlohmann_json,INTERFACE_INCLUDE_DIRECTORIES>
+    )
+
 
 # Only for win32 cross compilation using MXE
 if( WIN32 AND MSYS )
@@ -168,6 +172,8 @@ set( COMMON_DLG_SRCS
     dialogs/dialog_image_editor.cpp
     dialogs/dialog_image_editor_base.cpp
     dialogs/dialog_list_selector_base.cpp
+    dialogs/dialog_migrate_settings.cpp
+    dialogs/dialog_migrate_settings_base.cpp
     dialogs/dialog_page_settings_base.cpp
     dialogs/dialog_text_entry_base.cpp
     dialogs/dialog_print_generic.cpp
@@ -262,7 +268,6 @@ set( COMMON_SRCS
     bitmap_base.cpp
     board_printout.cpp
     build_version.cpp
-    colors_design_settings.cpp
     colors.cpp
     commit.cpp
     common.cpp
@@ -322,7 +327,6 @@ set( COMMON_SRCS
     richio.cpp
     search_stack.cpp
     searchhelpfilefullpath.cpp
-    settings.cpp
     status_popup.cpp
     systemdirsappend.cpp
     trace_helpers.cpp
@@ -382,6 +386,13 @@ set( COMMON_SRCS
     tool/zoom_menu.cpp
     tool/zoom_tool.cpp
 
+    settings/app_settings.cpp
+    settings/color_settings.cpp
+    settings/common_settings.cpp
+    settings/json_settings.cpp
+    settings/nested_settings.cpp
+    settings/settings_manager.cpp
+
     libeval/numeric_evaluator.cpp
     )
 
@@ -407,6 +418,10 @@ target_link_libraries( common
     ${wxWidgets_LIBRARIES}
     )
 
+target_include_directories( common PUBLIC
+    $<TARGET_PROPERTY:nlohmann_json,INTERFACE_INCLUDE_DIRECTORIES>
+    )
+
 
 set( PCB_COMMON_SRCS
     base_screen.cpp
@@ -445,6 +460,7 @@ set( PCB_COMMON_SRCS
     ${CMAKE_SOURCE_DIR}/pcbnew/convert_drawsegment_list_to_polygon.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/drc/drc_item.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/eagle_plugin.cpp
+    ${CMAKE_SOURCE_DIR}/pcbnew/footprint_editor_settings.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/gpcb_plugin.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/io_mgr.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/kicad_clipboard.cpp
@@ -452,18 +468,18 @@ set( PCB_COMMON_SRCS
     ${CMAKE_SOURCE_DIR}/pcbnew/kicad_plugin.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/netlist_reader/legacy_netlist_reader.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/legacy_plugin.cpp
-    ${CMAKE_SOURCE_DIR}/pcbnew//netlist_reader/netlist_reader.cpp
+    ${CMAKE_SOURCE_DIR}/pcbnew/netlist_reader/netlist_reader.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/pad_custom_shape_functions.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/pad_print_functions.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/pcb_display_options.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/pcb_draw_panel_gal.cpp
-    ${CMAKE_SOURCE_DIR}/pcbnew/pcb_general_settings.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/netlist_reader/pcb_netlist.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/pcb_painter.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/pcb_parser.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/pcb_plot_params.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/pcb_screen.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/pcb_view.cpp
+    ${CMAKE_SOURCE_DIR}/pcbnew/pcbnew_settings.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/plugin.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/ratsnest_data.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/ratsnest_viewitem.cpp
diff --git a/common/advanced_config.cpp b/common/advanced_config.cpp
index 0ae9c39e4c..952f31895a 100644
--- a/common/advanced_config.cpp
+++ b/common/advanced_config.cpp
@@ -25,6 +25,7 @@
 
 #include <common.h>
 #include <config_params.h>
+#include <settings/settings_manager.h>
 
 #include <wx/config.h>
 #include <wx/filename.h>
@@ -153,7 +154,7 @@ static void dumpCfg( const std::vector<PARAM_CFG*>& aArray )
 static wxFileName getAdvancedCfgFilename()
 {
     const static wxString cfg_filename{ "kicad_advanced" };
-    return wxFileName( GetKicadConfigPath(), cfg_filename );
+    return wxFileName( SETTINGS_MANAGER::GetUserSettingsPath(), cfg_filename );
 }
 
 
diff --git a/common/bin_mod.cpp b/common/bin_mod.cpp
index 74b0302c9d..84dfc9bff5 100644
--- a/common/bin_mod.cpp
+++ b/common/bin_mod.cpp
@@ -27,29 +27,26 @@
 #include <filehistory.h>
 #include <id.h>         // for ID_FILE1 and FILE_HISTORY_SIZE
 #include <pgm_base.h>
+#include <settings/app_settings.h>
+#include <settings/common_settings.h>
+#include <settings/settings_manager.h>
 
 
 BIN_MOD::BIN_MOD( const char* aName ) :
     m_name( aName ),
-    m_history( 0 )
+    m_config( nullptr ),
+    m_history( nullptr )
 {
 }
 
 
 void BIN_MOD::Init()
 {
-    // do an OS specific wxConfig instantiation, using the bin_mod (EXE/DLL/DSO) name.
-    m_config = GetNewConfig( wxString::FromUTF8( m_name ) );
-
-    // wxWidgets' implementation of this is *very* expensive, and we don't use them anyway.
-    m_config->SetExpandEnvVars( false );
-
     // get file history size from common settings
-    int fileHistorySize;
-    Pgm().CommonSettings()->Read( FILE_HISTORY_SIZE_KEY, &fileHistorySize, DEFAULT_FILE_HISTORY_SIZE );
+    int fileHistorySize = Pgm().GetCommonSettings()->m_System.file_history_size;
 
     m_history = new FILE_HISTORY( (unsigned) std::max( 0, fileHistorySize ), ID_FILE1 );
-    m_history->Load( *m_config.get() );
+    m_history->Load( *m_config );
 
     // Prepare On Line Help. Use only lower case for help file names, in order to
     // avoid problems with upper/lower case file names under windows and unix.
@@ -65,17 +62,22 @@ void BIN_MOD::End()
 {
     if( m_config )
     {
-        m_history->Save( *m_config.get() );
-        delete m_history;
+        if( m_history )
+        {
+            m_history->Save( *m_config );
+            delete m_history;
+            m_history = nullptr;
+        }
 
-        // Deleting a wxConfigBase writes its contents to disk if changed.
-        m_config.reset();
+        // The settings manager will outlive this module so we need to clean up the module level
+        // settings here instead of leaving it up to the manager
+        Pgm().GetSettingsManager().FlushAndRelease( m_config );
+        m_config = nullptr;
     }
 }
 
 
 BIN_MOD::~BIN_MOD()
 {
-    End();
 }
 
diff --git a/common/bitmap.cpp b/common/bitmap.cpp
index af2fd4327a..c10d29a6c2 100644
--- a/common/bitmap.cpp
+++ b/common/bitmap.cpp
@@ -39,6 +39,7 @@
 #include <pgm_base.h>
 #include <eda_base_frame.h>
 #include <eda_draw_frame.h>
+#include <settings/common_settings.h>
 
 
 struct SCALED_BITMAP_ID {
@@ -103,8 +104,7 @@ int KiIconScale( wxWindow* aWindow )
 
 static int get_scale_factor( EDA_BASE_FRAME* aWindow )
 {
-    int requested_scale;
-    Pgm().CommonSettings()->Read( ICON_SCALE_KEY, &requested_scale, 0 );
+    int requested_scale = Pgm().GetCommonSettings()->m_Appearance.icon_scale;
 
     if( requested_scale > 0 )
         return requested_scale;
@@ -223,8 +223,7 @@ bool SaveCanvasImageToFile( EDA_DRAW_FRAME* aFrame, const wxString& aFileName,
 void AddBitmapToMenuItem( wxMenuItem* aMenu, const wxBitmap& aImage )
 {
     // Retrieve the global applicaton show icon option:
-    bool useImagesInMenus;
-    Pgm().CommonSettings()->Read( USE_ICONS_IN_MENUS_KEY, &useImagesInMenus );
+    bool useImagesInMenus = Pgm().GetCommonSettings()->m_Appearance.use_icons_in_menus;
 
     wxItemKind menu_type = aMenu->GetKind();
 
diff --git a/common/board_printout.cpp b/common/board_printout.cpp
index dfc7e97258..7a0cf421ee 100644
--- a/common/board_printout.cpp
+++ b/common/board_printout.cpp
@@ -30,6 +30,7 @@
 #include <gal/gal_print.h>
 #include <painter.h>
 #include <pcbplot.h>
+#include <settings/app_settings.h>
 
 
 BOARD_PRINTOUT_SETTINGS::BOARD_PRINTOUT_SETTINGS( const PAGE_INFO& aPageInfo )
@@ -40,29 +41,26 @@ BOARD_PRINTOUT_SETTINGS::BOARD_PRINTOUT_SETTINGS( const PAGE_INFO& aPageInfo )
 }
 
 
-void BOARD_PRINTOUT_SETTINGS::Load( wxConfigBase* aConfig )
+void BOARD_PRINTOUT_SETTINGS::Load( APP_SETTINGS_BASE* aConfig )
 {
     PRINTOUT_SETTINGS::Load( aConfig );
 
-    for( unsigned layer = 0; layer < m_layerSet.size(); ++layer )
-    {
-        int tmp;
-        wxString key = wxString::Format( OPTKEY_LAYERBASE, layer );
-        aConfig->Read( key, &tmp, 1 );
-        m_layerSet.set( layer, tmp );
-    }
+    m_layerSet.reset();
+
+    for( int layer : aConfig->m_Printing.layers )
+        m_layerSet.set( layer, true );
 }
 
 
-void BOARD_PRINTOUT_SETTINGS::Save( wxConfigBase* aConfig )
+void BOARD_PRINTOUT_SETTINGS::Save( APP_SETTINGS_BASE* aConfig )
 {
     PRINTOUT_SETTINGS::Save( aConfig );
 
+    aConfig->m_Printing.layers.clear();
+
     for( unsigned layer = 0; layer < m_layerSet.size(); ++layer )
-    {
-        wxString key = wxString::Format( OPTKEY_LAYERBASE, layer );
-        aConfig->Write( key, m_layerSet.test( layer ) );
-    }
+        if( m_layerSet.test( layer ) )
+            aConfig->m_Printing.layers.push_back( layer );
 }
 
 
diff --git a/common/common.cpp b/common/common.cpp
index 687b8f2f7c..37ac4f7015 100644
--- a/common/common.cpp
+++ b/common/common.cpp
@@ -35,6 +35,7 @@
 #include <base_units.h>
 #include <reporter.h>
 #include <mutex>
+#include <settings/settings_manager.h>
 
 #include <wx/process.h>
 #include <wx/config.h>
@@ -246,60 +247,6 @@ timestamp_t GetNewTimeStamp()
 }
 
 
-std::unique_ptr<wxConfigBase> GetNewConfig( const wxString& aProgName )
-{
-    wxFileName configname;
-    configname.AssignDir( GetKicadConfigPath() );
-    configname.SetFullName( aProgName );
-
-    // explicitly use wxFileConfig to prevent storing any settings in the system registry on Windows
-    return std::make_unique<wxFileConfig>( wxT( "" ), wxT( "" ), configname.GetFullPath() );
-}
-
-
-wxString GetKicadConfigPath()
-{
-    wxFileName cfgpath;
-
-    // http://docs.wxwidgets.org/3.0/classwx_standard_paths.html#a7c7cf595d94d29147360d031647476b0
-    cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
-
-    // GetUserConfigDir() does not default to ~/.config which is the current standard
-    // configuration file location on Linux.  This has been fixed in later versions of wxWidgets.
-#if !defined( __WXMSW__ ) && !defined( __WXMAC__ )
-    wxArrayString dirs = cfgpath.GetDirs();
-
-    if( dirs.Last() != ".config" )
-        cfgpath.AppendDir( ".config" );
-#endif
-
-    wxString envstr;
-
-    // This shouldn't cause any issues on Windows or MacOS.
-    if( wxGetEnv( wxT( "XDG_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
-    {
-        // Override the assignment above with XDG_CONFIG_HOME
-        cfgpath.AssignDir( envstr );
-    }
-
-    cfgpath.AppendDir( TO_STR( KICAD_CONFIG_DIR ) );
-
-    // Use KICAD_CONFIG_HOME to allow the user to force a specific configuration path.
-    if( wxGetEnv( wxT( "KICAD_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
-    {
-        // Override the assignment above with KICAD_CONFIG_HOME
-        cfgpath.AssignDir( envstr );
-    }
-
-    if( !cfgpath.DirExists() )
-    {
-        cfgpath.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
-    }
-
-    return cfgpath.GetPath();
-}
-
-
 enum Bracket
 {
     Bracket_None,
diff --git a/common/dialogs/dialog_migrate_settings.cpp b/common/dialogs/dialog_migrate_settings.cpp
new file mode 100644
index 0000000000..5f5860f1c1
--- /dev/null
+++ b/common/dialogs/dialog_migrate_settings.cpp
@@ -0,0 +1,150 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 <bitmaps.h>
+#include <dialogs/dialog_migrate_settings.h>
+#include <settings/settings_manager.h>
+
+
+DIALOG_MIGRATE_SETTINGS::DIALOG_MIGRATE_SETTINGS( SETTINGS_MANAGER* aManager ) :
+        DIALOG_MIGRATE_SETTINGS_BASE( nullptr ), m_manager( aManager )
+{
+    m_standardButtonsCancel->SetLabel( _( "Quit KiCad" ) );
+
+    m_btnCustomPath->SetBitmap( KiBitmap( folder_xpm ) );
+
+    GetSizer()->SetSizeHints( this );
+    Centre();
+}
+
+
+DIALOG_MIGRATE_SETTINGS::~DIALOG_MIGRATE_SETTINGS()
+{
+}
+
+
+bool DIALOG_MIGRATE_SETTINGS::TransferDataToWindow()
+{
+    if( !wxDialog::TransferDataToWindow() )
+        return false;
+
+    wxString str;
+    str.Printf( _( "Welcome to KiCad %s!" ), SETTINGS_MANAGER::GetSettingsVersion() );
+    m_lblWelcome->SetLabelText( str );
+
+    std::vector<wxString> paths;
+
+    if( !m_manager->GetPreviousVersionPaths( &paths ) )
+    {
+        m_btnPrevVer->SetLabelText( _( "Import settings from a previous version (none found)" ) );
+        m_btnUseDefaults->SetValue( true );
+    }
+    else
+    {
+        m_cbPath->Clear();
+
+        for( const auto& path : paths )
+            m_cbPath->Append( path );
+
+        m_cbPath->SetSelection( 0 );
+        m_btnPrevVer->SetValue( true );
+    }
+
+    Fit();
+
+    return true;
+}
+
+
+bool DIALOG_MIGRATE_SETTINGS::TransferDataFromWindow()
+{
+    if( !wxDialog::TransferDataFromWindow() )
+        return false;
+
+    if( m_btnPrevVer->GetValue() )
+        m_manager->SetMigrationSource( m_cbPath->GetValue() );
+    else
+        m_manager->SetMigrationSource( wxEmptyString );
+
+    return true;
+}
+
+
+void DIALOG_MIGRATE_SETTINGS::OnPrevVerSelected( wxCommandEvent& event )
+{
+    m_standardButtons->GetAffirmativeButton()->Enable();
+    m_cbPath->Enable();
+    m_btnCustomPath->Enable();
+    validatePath();
+}
+
+
+void DIALOG_MIGRATE_SETTINGS::OnPathChanged( wxCommandEvent& event )
+{
+    validatePath();
+}
+
+
+void DIALOG_MIGRATE_SETTINGS::OnPathDefocused( wxFocusEvent& event )
+{
+    validatePath();
+}
+
+
+void DIALOG_MIGRATE_SETTINGS::OnChoosePath( wxCommandEvent& event )
+{
+    wxDirDialog dlg( nullptr, _( "Select Settings Path" ), m_cbPath->GetValue(),
+            wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST );
+
+    if( dlg.ShowModal() == wxID_OK )
+    {
+        m_cbPath->SetValue( dlg.GetPath() );
+        validatePath();
+    }
+}
+
+
+void DIALOG_MIGRATE_SETTINGS::OnDefaultSelected( wxCommandEvent& event )
+{
+    m_standardButtons->GetAffirmativeButton()->Enable();
+    m_cbPath->Disable();
+    m_btnCustomPath->Disable();
+    showPathError( false );
+}
+
+
+bool DIALOG_MIGRATE_SETTINGS::validatePath()
+{
+    wxString path = m_cbPath->GetValue();
+    bool valid = m_manager->IsSettingsPathValid( path );
+
+    showPathError( !valid );
+    m_standardButtons->GetAffirmativeButton()->Enable( valid && !path.IsEmpty() );
+
+    return valid;
+}
+
+
+void DIALOG_MIGRATE_SETTINGS::showPathError( bool aShow )
+{
+    m_lblPathError->Show( aShow );
+    Layout();
+    Fit();
+}
\ No newline at end of file
diff --git a/common/dialogs/dialog_migrate_settings.h b/common/dialogs/dialog_migrate_settings.h
new file mode 100644
index 0000000000..d65ac31580
--- /dev/null
+++ b/common/dialogs/dialog_migrate_settings.h
@@ -0,0 +1,62 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 _DIALOG_MIGRATE_SETTINGS_H
+#define _DIALOG_MIGRATE_SETTINGS_H
+
+#include "dialog_migrate_settings_base.h"
+
+
+class SETTINGS_MANAGER;
+
+
+class DIALOG_MIGRATE_SETTINGS : public DIALOG_MIGRATE_SETTINGS_BASE
+{
+public:
+    DIALOG_MIGRATE_SETTINGS( SETTINGS_MANAGER* aManager );
+
+    ~DIALOG_MIGRATE_SETTINGS() override;
+
+    bool TransferDataToWindow() override;
+
+    bool TransferDataFromWindow() override;
+
+protected:
+
+    void OnPrevVerSelected( wxCommandEvent& event ) override;
+
+    void OnPathChanged( wxCommandEvent& event ) override;
+
+    void OnPathDefocused( wxFocusEvent& event ) override;
+
+    void OnChoosePath( wxCommandEvent& event ) override;
+
+    void OnDefaultSelected( wxCommandEvent& event ) override;
+
+private:
+
+    bool validatePath();
+
+    void showPathError( bool aShow = true );
+
+    SETTINGS_MANAGER* m_manager;
+};
+
+#endif
diff --git a/common/dialogs/dialog_migrate_settings_base.cpp b/common/dialogs/dialog_migrate_settings_base.cpp
new file mode 100644
index 0000000000..5f2da19151
--- /dev/null
+++ b/common/dialogs/dialog_migrate_settings_base.cpp
@@ -0,0 +1,102 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#include "dialog_migrate_settings_base.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+DIALOG_MIGRATE_SETTINGS_BASE::DIALOG_MIGRATE_SETTINGS_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
+{
+	this->SetSizeHints( wxDefaultSize, wxDefaultSize );
+
+	m_sizer = new wxBoxSizer( wxVERTICAL );
+
+	wxBoxSizer* bSizer6;
+	bSizer6 = new wxBoxSizer( wxVERTICAL );
+
+	m_lblWelcome = new wxStaticText( this, wxID_ANY, wxT("Welcome to KiCad %s!"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_lblWelcome->Wrap( -1 );
+	m_lblWelcome->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD, false, wxEmptyString ) );
+
+	bSizer6->Add( m_lblWelcome, 0, wxALL, 5 );
+
+	m_staticText2 = new wxStaticText( this, wxID_ANY, wxT("How would you like to configure KiCad?"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_staticText2->Wrap( -1 );
+	bSizer6->Add( m_staticText2, 0, wxALL, 5 );
+
+	m_btnPrevVer = new wxRadioButton( this, wxID_ANY, wxT("Import settings from a previous version at:"), wxDefaultPosition, wxDefaultSize, 0 );
+	bSizer6->Add( m_btnPrevVer, 0, wxALL, 5 );
+
+	wxBoxSizer* bSizer5;
+	bSizer5 = new wxBoxSizer( wxHORIZONTAL );
+
+	m_cbPath = new wxComboBox( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, NULL, 0 );
+	m_cbPath->SetMinSize( wxSize( 480,-1 ) );
+
+	bSizer5->Add( m_cbPath, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+
+	m_btnCustomPath = new wxBitmapButton( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW|0 );
+	m_btnCustomPath->SetToolTip( wxT("Choose a different path") );
+
+	bSizer5->Add( m_btnCustomPath, 0, wxALL, 5 );
+
+
+	bSizer6->Add( bSizer5, 1, wxEXPAND, 5 );
+
+	m_lblPathError = new wxStaticText( this, wxID_ANY, wxT("The selected path does not contain valid KiCad settings!"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_lblPathError->Wrap( -1 );
+	m_lblPathError->SetForegroundColour( wxColour( 255, 43, 0 ) );
+	m_lblPathError->Hide();
+
+	bSizer6->Add( m_lblPathError, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
+
+	m_btnUseDefaults = new wxRadioButton( this, wxID_ANY, wxT("Start with default settings"), wxDefaultPosition, wxDefaultSize, 0 );
+	bSizer6->Add( m_btnUseDefaults, 0, wxALL, 5 );
+
+
+	m_sizer->Add( bSizer6, 0, wxEXPAND|wxLEFT|wxRIGHT|wxTOP, 5 );
+
+
+	m_sizer->Add( 0, 0, 1, wxEXPAND, 5 );
+
+	m_standardButtons = new wxStdDialogButtonSizer();
+	m_standardButtonsOK = new wxButton( this, wxID_OK );
+	m_standardButtons->AddButton( m_standardButtonsOK );
+	m_standardButtonsCancel = new wxButton( this, wxID_CANCEL );
+	m_standardButtons->AddButton( m_standardButtonsCancel );
+	m_standardButtons->Realize();
+	m_standardButtons->SetMinSize( wxSize( -1,50 ) );
+
+	m_sizer->Add( m_standardButtons, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 10 );
+
+
+	this->SetSizer( m_sizer );
+	this->Layout();
+	m_sizer->Fit( this );
+
+	this->Centre( wxBOTH );
+
+	// Connect Events
+	m_btnPrevVer->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnPrevVerSelected ), NULL, this );
+	m_cbPath->Connect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnPathChanged ), NULL, this );
+	m_cbPath->Connect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnPathDefocused ), NULL, this );
+	m_cbPath->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnPathChanged ), NULL, this );
+	m_btnCustomPath->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnChoosePath ), NULL, this );
+	m_btnUseDefaults->Connect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnDefaultSelected ), NULL, this );
+}
+
+DIALOG_MIGRATE_SETTINGS_BASE::~DIALOG_MIGRATE_SETTINGS_BASE()
+{
+	// Disconnect Events
+	m_btnPrevVer->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnPrevVerSelected ), NULL, this );
+	m_cbPath->Disconnect( wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnPathChanged ), NULL, this );
+	m_cbPath->Disconnect( wxEVT_KILL_FOCUS, wxFocusEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnPathDefocused ), NULL, this );
+	m_cbPath->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnPathChanged ), NULL, this );
+	m_btnCustomPath->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnChoosePath ), NULL, this );
+	m_btnUseDefaults->Disconnect( wxEVT_COMMAND_RADIOBUTTON_SELECTED, wxCommandEventHandler( DIALOG_MIGRATE_SETTINGS_BASE::OnDefaultSelected ), NULL, this );
+
+}
diff --git a/common/dialogs/dialog_migrate_settings_base.fbp b/common/dialogs/dialog_migrate_settings_base.fbp
new file mode 100644
index 0000000000..11e22eb20d
--- /dev/null
+++ b/common/dialogs/dialog_migrate_settings_base.fbp
@@ -0,0 +1,568 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<wxFormBuilder_Project>
+    <FileVersion major="1" minor="15" />
+    <object class="Project" expanded="1">
+        <property name="class_decoration">; </property>
+        <property name="code_generation">C++</property>
+        <property name="disconnect_events">1</property>
+        <property name="disconnect_mode">source_name</property>
+        <property name="disconnect_php_events">0</property>
+        <property name="disconnect_python_events">0</property>
+        <property name="embedded_files_path">res</property>
+        <property name="encoding">UTF-8</property>
+        <property name="event_generation">connect</property>
+        <property name="file">dialog_migrate_settings_base</property>
+        <property name="first_id">1000</property>
+        <property name="help_provider">none</property>
+        <property name="indent_with_spaces"></property>
+        <property name="internationalize">0</property>
+        <property name="name">DIALOG_MIGRATE_SETTINGS</property>
+        <property name="namespace"></property>
+        <property name="path">.</property>
+        <property name="precompiled_header"></property>
+        <property name="relative_path">1</property>
+        <property name="skip_lua_events">1</property>
+        <property name="skip_php_events">1</property>
+        <property name="skip_python_events">1</property>
+        <property name="ui_table">UI</property>
+        <property name="use_enum">0</property>
+        <property name="use_microsoft_bom">0</property>
+        <object class="Dialog" expanded="1">
+            <property name="aui_managed">0</property>
+            <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
+            <property name="bg"></property>
+            <property name="center">wxBOTH</property>
+            <property name="context_help"></property>
+            <property name="context_menu">1</property>
+            <property name="enabled">1</property>
+            <property name="event_handler">impl_virtual</property>
+            <property name="extra_style"></property>
+            <property name="fg"></property>
+            <property name="font"></property>
+            <property name="hidden">0</property>
+            <property name="id">wxID_ANY</property>
+            <property name="maximum_size"></property>
+            <property name="minimum_size"></property>
+            <property name="name">DIALOG_MIGRATE_SETTINGS_BASE</property>
+            <property name="pos"></property>
+            <property name="size"></property>
+            <property name="style">wxCAPTION</property>
+            <property name="subclass">DIALOG_SHIM; dialog_shim.h; forward_declare</property>
+            <property name="title">Configure KiCad Settings Path</property>
+            <property name="tooltip"></property>
+            <property name="window_extra_style"></property>
+            <property name="window_name"></property>
+            <property name="window_style"></property>
+            <object class="wxBoxSizer" expanded="1">
+                <property name="minimum_size">-1,-1</property>
+                <property name="name">m_sizer</property>
+                <property name="orient">wxVERTICAL</property>
+                <property name="permission">protected</property>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">5</property>
+                    <property name="flag">wxEXPAND|wxLEFT|wxRIGHT|wxTOP</property>
+                    <property name="proportion">0</property>
+                    <object class="wxBoxSizer" expanded="1">
+                        <property name="minimum_size"></property>
+                        <property name="name">bSizer6</property>
+                        <property name="orient">wxVERTICAL</property>
+                        <property name="permission">none</property>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALL</property>
+                            <property name="proportion">0</property>
+                            <object class="wxStaticText" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font">,90,92,-1,70,0</property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">Welcome to KiCad %s!</property>
+                                <property name="markup">0</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size">-1,-1</property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_lblWelcome</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <property name="wrap">-1</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALL</property>
+                            <property name="proportion">0</property>
+                            <object class="wxStaticText" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">How would you like to configure KiCad?</property>
+                                <property name="markup">0</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_staticText2</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <property name="wrap">-1</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALL</property>
+                            <property name="proportion">0</property>
+                            <object class="wxRadioButton" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">Import settings from a previous version at:</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_btnPrevVer</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="validator_data_type"></property>
+                                <property name="validator_style">wxFILTER_NONE</property>
+                                <property name="validator_type">wxDefaultValidator</property>
+                                <property name="validator_variable"></property>
+                                <property name="value">0</property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <event name="OnRadioButton">OnPrevVerSelected</event>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxEXPAND</property>
+                            <property name="proportion">1</property>
+                            <object class="wxBoxSizer" expanded="1">
+                                <property name="minimum_size"></property>
+                                <property name="name">bSizer5</property>
+                                <property name="orient">wxHORIZONTAL</property>
+                                <property name="permission">none</property>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
+                                    <property name="proportion">0</property>
+                                    <object class="wxComboBox" expanded="1">
+                                        <property name="BottomDockable">1</property>
+                                        <property name="LeftDockable">1</property>
+                                        <property name="RightDockable">1</property>
+                                        <property name="TopDockable">1</property>
+                                        <property name="aui_layer"></property>
+                                        <property name="aui_name"></property>
+                                        <property name="aui_position"></property>
+                                        <property name="aui_row"></property>
+                                        <property name="best_size"></property>
+                                        <property name="bg"></property>
+                                        <property name="caption"></property>
+                                        <property name="caption_visible">1</property>
+                                        <property name="center_pane">0</property>
+                                        <property name="choices"></property>
+                                        <property name="close_button">1</property>
+                                        <property name="context_help"></property>
+                                        <property name="context_menu">1</property>
+                                        <property name="default_pane">0</property>
+                                        <property name="dock">Dock</property>
+                                        <property name="dock_fixed">0</property>
+                                        <property name="docking">Left</property>
+                                        <property name="enabled">1</property>
+                                        <property name="fg"></property>
+                                        <property name="floatable">1</property>
+                                        <property name="font"></property>
+                                        <property name="gripper">0</property>
+                                        <property name="hidden">0</property>
+                                        <property name="id">wxID_ANY</property>
+                                        <property name="max_size"></property>
+                                        <property name="maximize_button">0</property>
+                                        <property name="maximum_size"></property>
+                                        <property name="min_size"></property>
+                                        <property name="minimize_button">0</property>
+                                        <property name="minimum_size">480,-1</property>
+                                        <property name="moveable">1</property>
+                                        <property name="name">m_cbPath</property>
+                                        <property name="pane_border">1</property>
+                                        <property name="pane_position"></property>
+                                        <property name="pane_size"></property>
+                                        <property name="permission">protected</property>
+                                        <property name="pin_button">1</property>
+                                        <property name="pos"></property>
+                                        <property name="resize">Resizable</property>
+                                        <property name="selection">-1</property>
+                                        <property name="show">1</property>
+                                        <property name="size"></property>
+                                        <property name="style"></property>
+                                        <property name="subclass">; ; forward_declare</property>
+                                        <property name="toolbar_pane">0</property>
+                                        <property name="tooltip"></property>
+                                        <property name="validator_data_type"></property>
+                                        <property name="validator_style">wxFILTER_NONE</property>
+                                        <property name="validator_type">wxDefaultValidator</property>
+                                        <property name="validator_variable"></property>
+                                        <property name="value"></property>
+                                        <property name="window_extra_style"></property>
+                                        <property name="window_name"></property>
+                                        <property name="window_style"></property>
+                                        <event name="OnCombobox">OnPathChanged</event>
+                                        <event name="OnKillFocus">OnPathDefocused</event>
+                                        <event name="OnTextEnter">OnPathChanged</event>
+                                    </object>
+                                </object>
+                                <object class="sizeritem" expanded="1">
+                                    <property name="border">5</property>
+                                    <property name="flag">wxALL</property>
+                                    <property name="proportion">0</property>
+                                    <object class="wxBitmapButton" expanded="1">
+                                        <property name="BottomDockable">1</property>
+                                        <property name="LeftDockable">1</property>
+                                        <property name="RightDockable">1</property>
+                                        <property name="TopDockable">1</property>
+                                        <property name="aui_layer"></property>
+                                        <property name="aui_name"></property>
+                                        <property name="aui_position"></property>
+                                        <property name="aui_row"></property>
+                                        <property name="best_size"></property>
+                                        <property name="bg"></property>
+                                        <property name="bitmap"></property>
+                                        <property name="caption"></property>
+                                        <property name="caption_visible">1</property>
+                                        <property name="center_pane">0</property>
+                                        <property name="close_button">1</property>
+                                        <property name="context_help"></property>
+                                        <property name="context_menu">1</property>
+                                        <property name="current"></property>
+                                        <property name="default">0</property>
+                                        <property name="default_pane">0</property>
+                                        <property name="disabled"></property>
+                                        <property name="dock">Dock</property>
+                                        <property name="dock_fixed">0</property>
+                                        <property name="docking">Left</property>
+                                        <property name="enabled">1</property>
+                                        <property name="fg"></property>
+                                        <property name="floatable">1</property>
+                                        <property name="focus"></property>
+                                        <property name="font"></property>
+                                        <property name="gripper">0</property>
+                                        <property name="hidden">0</property>
+                                        <property name="id">wxID_ANY</property>
+                                        <property name="label">Choose Path</property>
+                                        <property name="margins"></property>
+                                        <property name="markup">0</property>
+                                        <property name="max_size"></property>
+                                        <property name="maximize_button">0</property>
+                                        <property name="maximum_size"></property>
+                                        <property name="min_size"></property>
+                                        <property name="minimize_button">0</property>
+                                        <property name="minimum_size"></property>
+                                        <property name="moveable">1</property>
+                                        <property name="name">m_btnCustomPath</property>
+                                        <property name="pane_border">1</property>
+                                        <property name="pane_position"></property>
+                                        <property name="pane_size"></property>
+                                        <property name="permission">protected</property>
+                                        <property name="pin_button">1</property>
+                                        <property name="pos"></property>
+                                        <property name="position"></property>
+                                        <property name="pressed"></property>
+                                        <property name="resize">Resizable</property>
+                                        <property name="show">1</property>
+                                        <property name="size"></property>
+                                        <property name="style"></property>
+                                        <property name="subclass">; ; forward_declare</property>
+                                        <property name="toolbar_pane">0</property>
+                                        <property name="tooltip">Choose a different path</property>
+                                        <property name="validator_data_type"></property>
+                                        <property name="validator_style">wxFILTER_NONE</property>
+                                        <property name="validator_type">wxDefaultValidator</property>
+                                        <property name="validator_variable"></property>
+                                        <property name="window_extra_style"></property>
+                                        <property name="window_name"></property>
+                                        <property name="window_style"></property>
+                                        <event name="OnButtonClick">OnChoosePath</event>
+                                    </object>
+                                </object>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALIGN_CENTER_HORIZONTAL|wxALL</property>
+                            <property name="proportion">0</property>
+                            <object class="wxStaticText" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg">255,43,0</property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">1</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">The selected path does not contain valid KiCad settings!</property>
+                                <property name="markup">0</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_lblPathError</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <property name="wrap">-1</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALL</property>
+                            <property name="proportion">0</property>
+                            <object class="wxRadioButton" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">Start with default settings</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_btnUseDefaults</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="validator_data_type"></property>
+                                <property name="validator_style">wxFILTER_NONE</property>
+                                <property name="validator_type">wxDefaultValidator</property>
+                                <property name="validator_variable"></property>
+                                <property name="value">0</property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <event name="OnRadioButton">OnDefaultSelected</event>
+                            </object>
+                        </object>
+                    </object>
+                </object>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">5</property>
+                    <property name="flag">wxEXPAND</property>
+                    <property name="proportion">1</property>
+                    <object class="spacer" expanded="1">
+                        <property name="height">0</property>
+                        <property name="permission">protected</property>
+                        <property name="width">0</property>
+                    </object>
+                </object>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">10</property>
+                    <property name="flag">wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property>
+                    <property name="proportion">0</property>
+                    <object class="wxStdDialogButtonSizer" expanded="1">
+                        <property name="Apply">0</property>
+                        <property name="Cancel">1</property>
+                        <property name="ContextHelp">0</property>
+                        <property name="Help">0</property>
+                        <property name="No">0</property>
+                        <property name="OK">1</property>
+                        <property name="Save">0</property>
+                        <property name="Yes">0</property>
+                        <property name="minimum_size">-1,50</property>
+                        <property name="name">m_standardButtons</property>
+                        <property name="permission">protected</property>
+                    </object>
+                </object>
+            </object>
+        </object>
+    </object>
+</wxFormBuilder_Project>
diff --git a/common/dialogs/dialog_migrate_settings_base.h b/common/dialogs/dialog_migrate_settings_base.h
new file mode 100644
index 0000000000..cbd95ba6cd
--- /dev/null
+++ b/common/dialogs/dialog_migrate_settings_base.h
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include <wx/artprov.h>
+#include <wx/xrc/xmlres.h>
+#include "dialog_shim.h"
+#include <wx/string.h>
+#include <wx/stattext.h>
+#include <wx/gdicmn.h>
+#include <wx/font.h>
+#include <wx/colour.h>
+#include <wx/settings.h>
+#include <wx/radiobut.h>
+#include <wx/combobox.h>
+#include <wx/bmpbuttn.h>
+#include <wx/bitmap.h>
+#include <wx/image.h>
+#include <wx/icon.h>
+#include <wx/button.h>
+#include <wx/sizer.h>
+#include <wx/dialog.h>
+
+///////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class DIALOG_MIGRATE_SETTINGS_BASE
+///////////////////////////////////////////////////////////////////////////////
+class DIALOG_MIGRATE_SETTINGS_BASE : public DIALOG_SHIM
+{
+	private:
+
+	protected:
+		wxBoxSizer* m_sizer;
+		wxStaticText* m_lblWelcome;
+		wxStaticText* m_staticText2;
+		wxRadioButton* m_btnPrevVer;
+		wxComboBox* m_cbPath;
+		wxBitmapButton* m_btnCustomPath;
+		wxStaticText* m_lblPathError;
+		wxRadioButton* m_btnUseDefaults;
+		wxStdDialogButtonSizer* m_standardButtons;
+		wxButton* m_standardButtonsOK;
+		wxButton* m_standardButtonsCancel;
+
+		// Virtual event handlers, overide them in your derived class
+		virtual void OnPrevVerSelected( wxCommandEvent& event ) { event.Skip(); }
+		virtual void OnPathChanged( wxCommandEvent& event ) { event.Skip(); }
+		virtual void OnPathDefocused( wxFocusEvent& event ) { event.Skip(); }
+		virtual void OnChoosePath( wxCommandEvent& event ) { event.Skip(); }
+		virtual void OnDefaultSelected( wxCommandEvent& event ) { event.Skip(); }
+
+
+	public:
+
+		DIALOG_MIGRATE_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = wxT("Configure KiCad Settings Path"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxCAPTION );
+		~DIALOG_MIGRATE_SETTINGS_BASE();
+
+};
+
diff --git a/common/dialogs/dialog_page_settings.cpp b/common/dialogs/dialog_page_settings.cpp
index b84edb9bb4..b5c85673c1 100644
--- a/common/dialogs/dialog_page_settings.cpp
+++ b/common/dialogs/dialog_page_settings.cpp
@@ -44,26 +44,12 @@
 #ifdef EESCHEMA
 #include <general.h>
 #include <sch_screen.h>
+#include <eeschema_settings.h>
 #endif
 
 #define MAX_PAGE_EXAMPLE_SIZE 200
 
 
-#define KEY_EXPORT_REVISION      wxT( "PageSettingsExportRevision" )
-#define KEY_EXPORT_DATE          wxT( "PageSettingsExportDate" )
-#define KEY_EXPORT_TITLE         wxT( "PageSettingsExportTitle" )
-#define KEY_EXPORT_COMPANY       wxT( "PageSettingsExportCompany" )
-#define KEY_EXPORT_COMMENT1      wxT( "PageSettingsExportComment1" )
-#define KEY_EXPORT_COMMENT2      wxT( "PageSettingsExportComment2" )
-#define KEY_EXPORT_COMMENT3      wxT( "PageSettingsExportComment3" )
-#define KEY_EXPORT_COMMENT4      wxT( "PageSettingsExportComment4" )
-#define KEY_EXPORT_COMMENT5      wxT( "PageSettingsExportComment5" )
-#define KEY_EXPORT_COMMENT6      wxT( "PageSettingsExportComment6" )
-#define KEY_EXPORT_COMMENT7      wxT( "PageSettingsExportComment7" )
-#define KEY_EXPORT_COMMENT8      wxT( "PageSettingsExportComment8" )
-#define KEY_EXPORT_COMMENT9      wxT( "PageSettingsExportComment9" )
-
-
 // List of page formats.
 // they are prefixed by "_HKI" (already in use for hotkeys) instead of "_",
 // because we need both the translated and the not translated version.
@@ -135,20 +121,22 @@ DIALOG_PAGES_SETTINGS::DIALOG_PAGES_SETTINGS( EDA_DRAW_FRAME* parent, wxSize aMa
 DIALOG_PAGES_SETTINGS::~DIALOG_PAGES_SETTINGS()
 {
 #ifdef EESCHEMA
-    wxConfigBase* config = Kiface().KifaceSettings();
-    config->Write( KEY_EXPORT_REVISION, m_RevisionExport->GetValue() );
-    config->Write( KEY_EXPORT_DATE, m_DateExport->GetValue() );
-    config->Write( KEY_EXPORT_TITLE, m_TitleExport->GetValue() );
-    config->Write( KEY_EXPORT_COMPANY, m_CompanyExport->GetValue() );
-    config->Write( KEY_EXPORT_COMMENT1, m_Comment1Export->GetValue() );
-    config->Write( KEY_EXPORT_COMMENT2, m_Comment2Export->GetValue() );
-    config->Write( KEY_EXPORT_COMMENT3, m_Comment3Export->GetValue() );
-    config->Write( KEY_EXPORT_COMMENT4, m_Comment4Export->GetValue() );
-    config->Write( KEY_EXPORT_COMMENT5, m_Comment5Export->GetValue() );
-    config->Write( KEY_EXPORT_COMMENT6, m_Comment6Export->GetValue() );
-    config->Write( KEY_EXPORT_COMMENT7, m_Comment7Export->GetValue() );
-    config->Write( KEY_EXPORT_COMMENT8, m_Comment8Export->GetValue() );
-    config->Write( KEY_EXPORT_COMMENT9, m_Comment9Export->GetValue() );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+    wxASSERT( cfg );
+
+    cfg->m_PageSettings.export_revision = m_RevisionExport->GetValue();
+    cfg->m_PageSettings.export_date     = m_DateExport->GetValue();
+    cfg->m_PageSettings.export_title    = m_TitleExport->GetValue();
+    cfg->m_PageSettings.export_company  = m_CompanyExport->GetValue();
+    cfg->m_PageSettings.export_comment1 = m_Comment1Export->GetValue();
+    cfg->m_PageSettings.export_comment2 = m_Comment2Export->GetValue();
+    cfg->m_PageSettings.export_comment3 = m_Comment3Export->GetValue();
+    cfg->m_PageSettings.export_comment4 = m_Comment4Export->GetValue();
+    cfg->m_PageSettings.export_comment5 = m_Comment5Export->GetValue();
+    cfg->m_PageSettings.export_comment6 = m_Comment6Export->GetValue();
+    cfg->m_PageSettings.export_comment7 = m_Comment7Export->GetValue();
+    cfg->m_PageSettings.export_comment8 = m_Comment8Export->GetValue();
+    cfg->m_PageSettings.export_comment9 = m_Comment9Export->GetValue();
 #endif
 
     delete m_page_bitmap;
@@ -221,20 +209,22 @@ void DIALOG_PAGES_SETTINGS::initDialog()
     m_TextComment9->SetValue( m_tb.GetComment( 8 ) );
 
 #ifdef EESCHEMA
-    wxConfigBase* config = Kiface().KifaceSettings();
-    m_RevisionExport->SetValue( config->ReadBool( KEY_EXPORT_REVISION, false ) );
-    m_DateExport->SetValue( config->ReadBool( KEY_EXPORT_DATE, false ) );
-    m_TitleExport->SetValue( config->ReadBool( KEY_EXPORT_TITLE, false ) );
-    m_CompanyExport->SetValue( config->ReadBool( KEY_EXPORT_COMPANY, false ) );
-    m_Comment1Export->SetValue( config->ReadBool( KEY_EXPORT_COMMENT1, false ) );
-    m_Comment2Export->SetValue( config->ReadBool( KEY_EXPORT_COMMENT2, false ) );
-    m_Comment3Export->SetValue( config->ReadBool( KEY_EXPORT_COMMENT3, false ) );
-    m_Comment4Export->SetValue( config->ReadBool( KEY_EXPORT_COMMENT4, false ) );
-    m_Comment5Export->SetValue( config->ReadBool( KEY_EXPORT_COMMENT5, false ) );
-    m_Comment6Export->SetValue( config->ReadBool( KEY_EXPORT_COMMENT6, false ) );
-    m_Comment7Export->SetValue( config->ReadBool( KEY_EXPORT_COMMENT7, false ) );
-    m_Comment8Export->SetValue( config->ReadBool( KEY_EXPORT_COMMENT8, false ) );
-    m_Comment9Export->SetValue( config->ReadBool( KEY_EXPORT_COMMENT9, false ) );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+    wxASSERT( cfg );
+
+    m_RevisionExport->SetValue( cfg->m_PageSettings.export_revision );
+    m_DateExport->SetValue( cfg->m_PageSettings.export_date );
+    m_TitleExport->SetValue( cfg->m_PageSettings.export_title );
+    m_CompanyExport->SetValue( cfg->m_PageSettings.export_company  );
+    m_Comment1Export->SetValue( cfg->m_PageSettings.export_comment1 );
+    m_Comment2Export->SetValue( cfg->m_PageSettings.export_comment2 );
+    m_Comment3Export->SetValue( cfg->m_PageSettings.export_comment3 );
+    m_Comment4Export->SetValue( cfg->m_PageSettings.export_comment4 );
+    m_Comment5Export->SetValue( cfg->m_PageSettings.export_comment5 );
+    m_Comment6Export->SetValue( cfg->m_PageSettings.export_comment6 );
+    m_Comment7Export->SetValue( cfg->m_PageSettings.export_comment7 );
+    m_Comment8Export->SetValue( cfg->m_PageSettings.export_comment8 );
+    m_Comment9Export->SetValue( cfg->m_PageSettings.export_comment9 );
 #else
     m_RevisionExport->Show( false );
     m_DateExport->Show( false );
diff --git a/common/dialogs/dialog_print_generic.h b/common/dialogs/dialog_print_generic.h
index 5674ed4c58..031815d1d2 100644
--- a/common/dialogs/dialog_print_generic.h
+++ b/common/dialogs/dialog_print_generic.h
@@ -23,7 +23,6 @@
 #include <wx/valnum.h>
 #include <widgets/unit_binder.h>
 
-class wxConfigBase;
 class EDA_DRAW_FRAME;
 struct PRINTOUT_SETTINGS;
 
@@ -78,7 +77,7 @@ protected:
     // even if the dialog is closed without printing
     bool TransferDataToWindow() override;
 
-    wxConfigBase* m_config;
+    APP_SETTINGS_BASE* m_config;
 
     PRINTOUT_SETTINGS* m_settings;
 
diff --git a/common/dialogs/panel_common_settings.cpp b/common/dialogs/panel_common_settings.cpp
index 8a90976412..955528e62d 100644
--- a/common/dialogs/panel_common_settings.cpp
+++ b/common/dialogs/panel_common_settings.cpp
@@ -30,6 +30,8 @@
 #include <kiface_i.h>
 #include <pgm_base.h>
 #include <id.h>
+#include <settings/common_settings.h>
+#include <settings/settings_manager.h>
 
 static constexpr int dpi_scaling_precision = 1;
 static constexpr double dpi_scaling_increment = 0.5;
@@ -79,28 +81,20 @@ PANEL_COMMON_SETTINGS::~PANEL_COMMON_SETTINGS()
 
 bool PANEL_COMMON_SETTINGS::TransferDataToWindow()
 {
-    wxConfigBase* commonSettings = Pgm().CommonSettings();
+    COMMON_SETTINGS* commonSettings = Pgm().GetCommonSettings();
 
-    int timevalue;
+    int timevalue = commonSettings->m_System.autosave_interval;
     wxString msg;
 
-    commonSettings->Read( AUTOSAVE_INTERVAL_KEY, &timevalue );
     msg << timevalue / 60;
     m_SaveTime->SetValue( msg );
 
-    int fileHistorySize;
-    commonSettings->Read( FILE_HISTORY_SIZE_KEY, &fileHistorySize, DEFAULT_FILE_HISTORY_SIZE );
-    m_fileHistorySize->SetValue( fileHistorySize );
+    m_fileHistorySize->SetValue( commonSettings->m_System.file_history_size );
 
-    int antialiasingMode;
-    commonSettings->Read( GAL_ANTIALIASING_MODE_KEY, &antialiasingMode, 0 );
-    m_antialiasing->SetSelection( antialiasingMode );
+    m_antialiasing->SetSelection( commonSettings->m_Graphics.opengl_aa_mode );
+    m_antialiasingFallback->SetSelection( commonSettings->m_Graphics.cairo_aa_mode );
 
-    commonSettings->Read( CAIRO_ANTIALIASING_MODE_KEY, &antialiasingMode, 0 );
-    m_antialiasingFallback->SetSelection( antialiasingMode );
-
-    int icon_scale_fourths;
-    commonSettings->Read( ICON_SCALE_KEY, &icon_scale_fourths );
+    int icon_scale_fourths = commonSettings->m_Appearance.icon_scale;
 
     if( icon_scale_fourths <= 0 )
     {
@@ -119,33 +113,16 @@ bool PANEL_COMMON_SETTINGS::TransferDataToWindow()
         m_canvasScaleAuto->SetValue( dpi.GetCanvasIsAutoScaled() );
     }
 
-    bool option;
-    commonSettings->Read( USE_ICONS_IN_MENUS_KEY, &option );
-    m_checkBoxIconsInMenus->SetValue( option );
+    m_checkBoxIconsInMenus->SetValue( commonSettings->m_Appearance.use_icons_in_menus );
+    m_ZoomCenterOpt->SetValue( commonSettings->m_Input.center_on_zoom );
+    m_MousewheelPANOpt->SetValue( commonSettings->m_Input.mousewheel_pan );
+    m_AutoPANOpt->SetValue( commonSettings->m_Input.auto_pan );
 
-    commonSettings->Read( ENBL_ZOOM_NO_CENTER_KEY, &option );
-    m_ZoomCenterOpt->SetValue( !option );
-
-    commonSettings->Read( ENBL_MOUSEWHEEL_PAN_KEY, &option );
-    m_MousewheelPANOpt->SetValue( option );
-
-    commonSettings->Read( ENBL_AUTO_PAN_KEY, &option );
-    m_AutoPANOpt->SetValue( option );
-
-    if( !commonSettings->Read( PREFER_SELECT_TO_DRAG_KEY, &option ) )
-    {
-        // Legacy versions stored the property only for PCBNew, so see if we have it there
-        std::unique_ptr<wxConfigBase> pcbSettings = GetNewConfig( wxT( "pcbnew" ) );
-        pcbSettings->Read( "DragSelects", &option, true );
-    }
-    m_PreferSelectToDrag->SetValue( option );
-
-    commonSettings->Read( WARP_MOUSE_ON_MOVE_KEY, &option );
-    m_warpMouseOnMove->SetValue( option );
-
-    commonSettings->Read( IMMEDIATE_ACTIONS_KEY, &option );
-    m_NonImmediateActions->SetValue( !option );
+    m_PreferSelectToDrag->SetValue( commonSettings->m_Input.prefer_select_to_drag );
+    m_warpMouseOnMove->SetValue( commonSettings->m_Input.warp_mouse_on_move );
+    m_NonImmediateActions->SetValue( !commonSettings->m_Input.immediate_actions );
 
+    // TODO(JE) Move these into COMMON_SETTINGS probably
     m_textEditorPath->SetValue( Pgm().GetEditorName( false ) );
     m_defaultPDFViewer->SetValue( Pgm().UseSystemPdfBrowser() );
     m_otherPDFViewer->SetValue( !Pgm().UseSystemPdfBrowser() );
@@ -157,31 +134,30 @@ bool PANEL_COMMON_SETTINGS::TransferDataToWindow()
 
 bool PANEL_COMMON_SETTINGS::TransferDataFromWindow()
 {
-    wxConfigBase* commonSettings = Pgm().CommonSettings();
+    COMMON_SETTINGS* commonSettings = Pgm().GetCommonSettings();
 
-    commonSettings->Write( AUTOSAVE_INTERVAL_KEY, m_SaveTime->GetValue() * 60 );
+    commonSettings->m_System.autosave_interval = m_SaveTime->GetValue() * 60;
+    commonSettings->m_System.file_history_size = m_fileHistorySize->GetValue();
 
-    commonSettings->Write( FILE_HISTORY_SIZE_KEY, m_fileHistorySize->GetValue() );
-
-    commonSettings->Write( GAL_ANTIALIASING_MODE_KEY, m_antialiasing->GetSelection() );
-
-    commonSettings->Write( CAIRO_ANTIALIASING_MODE_KEY, m_antialiasingFallback->GetSelection() );
+    commonSettings->m_Graphics.opengl_aa_mode = m_antialiasing->GetSelection();
+    commonSettings->m_Graphics.cairo_aa_mode = m_antialiasingFallback->GetSelection();
 
     const int scale_fourths = m_iconScaleAuto->GetValue() ? -1 : m_iconScaleSlider->GetValue() / 25;
-    commonSettings->Write( ICON_SCALE_KEY, scale_fourths );
+    commonSettings->m_Appearance.icon_scale = scale_fourths;
 
     {
         DPI_SCALING dpi( commonSettings, this );
         dpi.SetDpiConfig( m_canvasScaleAuto->GetValue(), m_canvasScaleCtrl->GetValue() );
     }
 
-    commonSettings->Write( USE_ICONS_IN_MENUS_KEY, m_checkBoxIconsInMenus->GetValue() );
-    commonSettings->Write( ENBL_ZOOM_NO_CENTER_KEY, !m_ZoomCenterOpt->GetValue() );
-    commonSettings->Write( ENBL_MOUSEWHEEL_PAN_KEY, m_MousewheelPANOpt->GetValue() );
-    commonSettings->Write( ENBL_AUTO_PAN_KEY, m_AutoPANOpt->GetValue() );
-    commonSettings->Write( PREFER_SELECT_TO_DRAG_KEY, m_PreferSelectToDrag->GetValue() );
-    commonSettings->Write( WARP_MOUSE_ON_MOVE_KEY, m_warpMouseOnMove->GetValue() );
-    commonSettings->Write( IMMEDIATE_ACTIONS_KEY, !m_NonImmediateActions->GetValue() );
+    commonSettings->m_Appearance.use_icons_in_menus = m_checkBoxIconsInMenus->GetValue();
+
+    commonSettings->m_Input.auto_pan = m_AutoPANOpt->GetValue();
+    commonSettings->m_Input.center_on_zoom = m_ZoomCenterOpt->GetValue();
+    commonSettings->m_Input.immediate_actions = !m_NonImmediateActions->GetValue();
+    commonSettings->m_Input.mousewheel_pan = m_MousewheelPANOpt->GetValue();
+    commonSettings->m_Input.prefer_select_to_drag = m_PreferSelectToDrag->GetValue();
+    commonSettings->m_Input.warp_mouse_on_move = m_warpMouseOnMove->GetValue();
 
     Pgm().SetEditorName( m_textEditorPath->GetValue() );
 
@@ -189,6 +165,8 @@ bool PANEL_COMMON_SETTINGS::TransferDataFromWindow()
     Pgm().ForceSystemPdfBrowser( m_defaultPDFViewer->GetValue() );
     Pgm().WritePdfBrowserInfos();
 
+    Pgm().GetSettingsManager().Save( commonSettings );
+
     return true;
 }
 
diff --git a/common/dpi_scaling.cpp b/common/dpi_scaling.cpp
index bdd27d540b..7bdc2dc633 100644
--- a/common/dpi_scaling.cpp
+++ b/common/dpi_scaling.cpp
@@ -27,8 +27,8 @@
 
 #include <env_vars.h>
 #include <pgm_base.h>
+#include <settings/common_settings.h>
 
-#include <wx/config.h>
 #include <wx/log.h>
 
 
@@ -47,11 +47,10 @@ const wxChar* const traceHiDpi = wxT( "KICAD_TRACE_HIGH_DPI" );
  *
  * @return the scale factor, if set
  */
-static OPT<double> getKiCadConfiguredScale( const wxConfigBase& aConfig )
+static OPT<double> getKiCadConfiguredScale( const COMMON_SETTINGS& aConfig )
 {
     OPT<double> scale;
-    double      canvas_scale = 0.0;
-    aConfig.Read( CANVAS_SCALE_KEY, &canvas_scale, 0.0 );
+    double      canvas_scale = aConfig.m_Appearance.canvas_scale;
 
     if( canvas_scale > 0.0 )
     {
@@ -93,7 +92,7 @@ static OPT<double> getEnviromentScale()
 }
 
 
-DPI_SCALING::DPI_SCALING( wxConfigBase* aConfig, const wxWindow* aWindow )
+DPI_SCALING::DPI_SCALING( COMMON_SETTINGS* aConfig, const wxWindow* aWindow )
         : m_config( aConfig ), m_window( aWindow )
 {
 }
@@ -153,7 +152,7 @@ void DPI_SCALING::SetDpiConfig( bool aAuto, double aValue )
 
     const double value = aAuto ? 0.0 : aValue;
 
-    m_config->Write( CANVAS_SCALE_KEY, value );
+    m_config->m_Appearance.canvas_scale = value;
 }
 
 
diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp
index ec0b3cd9ec..6b719dedd5 100644
--- a/common/draw_panel_gal.cpp
+++ b/common/draw_panel_gal.cpp
@@ -24,9 +24,10 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <confirm.h>
 #include <eda_draw_frame.h>
 #include <kiface_i.h>
-#include <confirm.h>
+#include <settings/app_settings.h>
 
 #include <class_draw_panel_gal.h>
 #include <view/view.h>
diff --git a/common/eda_base_frame.cpp b/common/eda_base_frame.cpp
index deb66322b9..e7ea6dffc2 100644
--- a/common/eda_base_frame.cpp
+++ b/common/eda_base_frame.cpp
@@ -23,48 +23,28 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <wx/stdpaths.h>
-#include <wx/string.h>
-#include <wx/display.h>
+#include <bitmaps.h>
 #include <dialog_shim.h>
+#include <dialogs/panel_common_settings.h>
+#include <filehistory.h>
 #include <id.h>
 #include <kiface_i.h>
-#include <pgm_base.h>
-#include <trace_helpers.h>
+#include <menus_helpers.h>
 #include <panel_hotkeys_editor.h>
-#include <dialogs/panel_common_settings.h>
-#include <widgets/paged_dialog.h>
-#include <bitmaps.h>
+#include <pgm_base.h>
+#include <settings/app_settings.h>
+#include <settings/common_settings.h>
+#include <settings/settings_manager.h>
+#include <tool/action_manager.h>
 #include <tool/action_menu.h>
+#include <tool/actions.h>
 #include <tool/common_control.h>
 #include <tool/tool_manager.h>
-#include <tool/action_manager.h>
-#include <menus_helpers.h>
-#include <tool/actions.h>
-#include <filehistory.h>
-
-
-/// The default auto save interval is 10 minutes.
-#define DEFAULT_AUTO_SAVE_INTERVAL 600
-
-///@{
-/// \ingroup config
-
-/// Configuration file entry name for auto save interval.
-static const wxString entryAutoSaveInterval = "AutoSaveInterval";
-
-/// Configuration file entry for wxAuiManger perspective.
-static const wxString entryPerspective = "Perspective";
-
-/// Configuration file entry for most recently used path.
-static const wxString entryMruPath = "MostRecentlyUsedPath";
-
-static const wxString entryPosY = "Pos_y";   ///< Y position of frame, in pixels (suffix)
-static const wxString entryPosX = "Pos_x";   ///< X position of frame, in pixels (suffix)
-static const wxString entrySizeY = "Size_y"; ///< Height of frame, in pixels (suffix)
-static const wxString entrySizeX = "Size_x"; ///< Width of frame, in pixels (suffix)
-static const wxString entryMaximized = "Maximized";  ///< Nonzero iff frame is maximized (suffix)
-///@}
+#include <trace_helpers.h>
+#include <widgets/paged_dialog.h>
+#include <wx/display.h>
+#include <wx/stdpaths.h>
+#include <wx/string.h>
 
 
 BEGIN_EVENT_TABLE( EDA_BASE_FRAME, wxFrame )
@@ -95,6 +75,7 @@ EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType,
     m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
     m_mruPath = wxStandardPaths::Get().GetDocumentsDir();
     m_toolManager = nullptr;
+    m_settingsManager = nullptr;
 
     // Gives a reasonable minimal size to the frame:
     const int minsize_x = 500;
@@ -151,7 +132,7 @@ void EDA_BASE_FRAME::windowClosing( wxCloseEvent& event )
         return;
     }
 
-    wxConfigBase* cfg = config();
+    APP_SETTINGS_BASE* cfg = config();
 
     if( cfg )
         SaveSettings( cfg );    // virtual, wxFrame specific
@@ -450,40 +431,30 @@ void EDA_BASE_FRAME::CommonSettingsChanged( bool aEnvVarsChanged )
         GetMenuBar()->Refresh();
     }
 
-    wxConfigBase* settings = Pgm().CommonSettings();
+    COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
 
-    settings->Read( WARP_MOUSE_ON_MOVE_KEY, &m_moveWarpsCursor );
-    settings->Read( PREFER_SELECT_TO_DRAG_KEY, &m_dragSelects );
-    settings->Read( IMMEDIATE_ACTIONS_KEY, &m_immediateActions );
+    m_moveWarpsCursor = settings->m_Input.warp_mouse_on_move;
+    m_dragSelects = settings->m_Input.prefer_select_to_drag;
+    m_immediateActions = settings->m_Input.immediate_actions;
 }
 
 
-void EDA_BASE_FRAME::LoadSettings( wxConfigBase* aCfg )
+void EDA_BASE_FRAME::LoadWindowSettings( WINDOW_SETTINGS* aCfg )
 {
-    int maximized = 0;
+    m_FramePos.x = aCfg->pos_x;
+    m_FramePos.y = aCfg->pos_y;
+    m_FrameSize.x = aCfg->size_x;
+    m_FrameSize.y = aCfg->size_y;
 
-    wxString baseCfgName = ConfigBaseName();
-
-    wxString text = baseCfgName + entryPosX;
-    aCfg->Read( text, &m_FramePos.x, m_FramePos.x );
-
-    text = baseCfgName + entryPosY;
-    aCfg->Read( text, &m_FramePos.y, m_FramePos.y );
-
-    text = baseCfgName + entrySizeX;
-    aCfg->Read( text, &m_FrameSize.x, m_FrameSize.x );
-
-    text = baseCfgName + entrySizeY;
-    aCfg->Read( text, &m_FrameSize.y, m_FrameSize.y );
-
-    text = baseCfgName + entryMaximized;
-    aCfg->Read( text, &maximized, 0 );
+    // Ensure minimum size is set if the stored config was zero-initialized
+    if( m_FrameSize.x < GetMinWidth() || m_FrameSize.y < GetMinHeight() )
+    {
+        m_FrameSize.x = GetMinWidth();
+        m_FrameSize.y = GetMinHeight();
+    }
 
     if( m_hasAutoSave )
-    {
-        text = baseCfgName + entryAutoSaveInterval;
-        aCfg->Read( text, &m_autoSaveInterval, DEFAULT_AUTO_SAVE_INTERVAL );
-    }
+        m_autoSaveInterval = Pgm().GetCommonSettings()->m_System.autosave_interval;
 
     // Ensure the window is on a connected display, and is visible.
     // (at least a corner of the frame must be visible on screen)
@@ -510,33 +481,21 @@ void EDA_BASE_FRAME::LoadSettings( wxConfigBase* aCfg )
     if( m_FramePos.y < Ypos_min )
         m_FramePos.y = Ypos_min;
 
-    if( maximized )
+    if( aCfg->maximized )
         Maximize();
 
-    aCfg->Read( baseCfgName + entryPerspective, &m_perspective );
-    aCfg->Read( baseCfgName + entryMruPath, &m_mruPath );
+    m_perspective = aCfg->perspective;
+    m_mruPath = aCfg->mru_path;
 
-    wxConfigBase* settings = Pgm().CommonSettings();
+    COMMON_SETTINGS* settings = Pgm().GetCommonSettings();
 
-    if( !settings->Read( WARP_MOUSE_ON_MOVE_KEY, &m_moveWarpsCursor ) )
-    {
-        // Legacy versions stored the property only for Eeschema, so see if we have it there
-        std::unique_ptr<wxConfigBase> pcbSettings = GetNewConfig( wxT( "eeschema" ) );
-        pcbSettings->Read( "MoveWarpsCursor", &m_moveWarpsCursor, true );
-    }
-
-    if( !settings->Read( PREFER_SELECT_TO_DRAG_KEY, &m_dragSelects ) )
-    {
-        // Legacy versions stored the property only for PCBNew, so see if we have it there
-        std::unique_ptr<wxConfigBase> pcbSettings = GetNewConfig( wxT( "pcbnew" ) );
-        pcbSettings->Read( "DragSelects", &m_dragSelects, true );
-    }
-
-    settings->Read( IMMEDIATE_ACTIONS_KEY, &m_immediateActions, false );
+    m_moveWarpsCursor = settings->m_Input.warp_mouse_on_move;
+    m_dragSelects = settings->m_Input.prefer_select_to_drag;
+    m_immediateActions = settings->m_Input.immediate_actions;
 }
 
 
-void EDA_BASE_FRAME::SaveSettings( wxConfigBase* aCfg )
+void EDA_BASE_FRAME::SaveWindowSettings( WINDOW_SETTINGS* aCfg )
 {
     wxString        text;
 
@@ -548,43 +507,47 @@ void EDA_BASE_FRAME::SaveSettings( wxConfigBase* aCfg )
     m_FrameSize = GetSize();
     m_FramePos  = GetPosition();
 
-    text = baseCfgName + wxT( "Pos_x" );
-    aCfg->Write( text, (long) m_FramePos.x );
-
-    text = baseCfgName + wxT( "Pos_y" );
-    aCfg->Write( text, (long) m_FramePos.y );
-
-    text = baseCfgName + wxT( "Size_x" );
-    aCfg->Write( text, (long) m_FrameSize.x );
-
-    text = baseCfgName + wxT( "Size_y" );
-    aCfg->Write( text, (long) m_FrameSize.y );
-
-    text = baseCfgName + wxT( "Maximized" );
-    aCfg->Write( text, IsMaximized() );
+    aCfg->pos_x = m_FramePos.x;
+    aCfg->pos_y = m_FramePos.y;
+    aCfg->size_x = m_FrameSize.x;
+    aCfg->size_y = m_FrameSize.y;
+    aCfg->maximized = IsMaximized();
 
+    // TODO(JE) should auto-save in common settings be overwritten by every app?
     if( m_hasAutoSave )
-    {
-        text = baseCfgName + entryAutoSaveInterval;
-        aCfg->Write( text, m_autoSaveInterval );
-    }
+        Pgm().GetCommonSettings()->m_System.autosave_interval = m_autoSaveInterval;
 
     // Once this is fully implemented, wxAuiManager will be used to maintain
     // the persistance of the main frame and all it's managed windows and
     // all of the legacy frame persistence position code can be removed.
-    wxString perspective = m_auimgr.SavePerspective();
+    aCfg->perspective = m_auimgr.SavePerspective().ToStdString();
 
-    // printf( "perspective(%s): %s\n",
-    //    TO_UTF8( m_FrameName + entryPerspective ), TO_UTF8( perspective ) );
-    aCfg->Write( baseCfgName + entryPerspective, perspective );
-    aCfg->Write( baseCfgName + entryMruPath, m_mruPath );
+    aCfg->mru_path = m_mruPath;
 }
 
 
-wxConfigBase* EDA_BASE_FRAME::config()
+void EDA_BASE_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
+{
+    LoadWindowSettings( GetWindowSettings( aCfg ) );
+}
+
+
+void EDA_BASE_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
+{
+    SaveWindowSettings( GetWindowSettings( aCfg ) );
+}
+
+
+WINDOW_SETTINGS* EDA_BASE_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
+{
+    return &aCfg->m_Window;
+}
+
+
+APP_SETTINGS_BASE* EDA_BASE_FRAME::config()
 {
     // KICAD_MANAGER_FRAME overrides this
-    wxConfigBase* ret = Kiface().KifaceSettings();
+    APP_SETTINGS_BASE* ret = Kiface().KifaceSettings();
     //wxASSERT( ret );
     return ret;
 }
diff --git a/common/eda_doc.cpp b/common/eda_doc.cpp
index 5d073a02de..0ab00e63fd 100644
--- a/common/eda_doc.cpp
+++ b/common/eda_doc.cpp
@@ -31,6 +31,7 @@
 #include <common.h>
 #include <confirm.h>
 #include <gestfich.h>
+#include <settings/common_settings.h>
 
 #include <wx/mimetype.h>
 #include <wx/tokenzr.h>
@@ -41,23 +42,15 @@
 
 void PGM_BASE::ReadPdfBrowserInfos()
 {
-    wxASSERT( m_common_settings );
-
-    wxString browser = m_common_settings->Read( wxT( "PdfBrowserName" ), wxEmptyString );
-    SetPdfBrowserName( browser );
-
-    int tmp;
-    m_common_settings->Read( wxT( "UseSystemBrowser" ), &tmp, 0 );
-    m_use_system_pdf_browser = bool( tmp );
+    SetPdfBrowserName( GetCommonSettings()->m_System.pdf_viewer_name );
+    m_use_system_pdf_browser = GetCommonSettings()->m_System.use_system_pdf_viewer;
 }
 
 
 void PGM_BASE::WritePdfBrowserInfos()
 {
-    wxASSERT( m_common_settings );
-
-    m_common_settings->Write( wxT( "PdfBrowserName" ), GetPdfBrowserName() );
-    m_common_settings->Write( wxT( "UseSystemBrowser" ), m_use_system_pdf_browser );
+    GetCommonSettings()->m_System.pdf_viewer_name = GetPdfBrowserName();
+    GetCommonSettings()->m_System.use_system_pdf_viewer = m_use_system_pdf_browser;
 }
 
 
diff --git a/common/eda_draw_frame.cpp b/common/eda_draw_frame.cpp
index e4c8fec772..95566a5139 100644
--- a/common/eda_draw_frame.cpp
+++ b/common/eda_draw_frame.cpp
@@ -23,64 +23,43 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <pgm_base.h>
-#include <kiface_i.h>
-#include <bitmaps.h>
-#include <macros.h>
-#include <id.h>
 #include <base_screen.h>
-#include <msgpanel.h>
-#include <eda_draw_frame.h>
+#include <bitmaps.h>
 #include <confirm.h>
 #include <dialog_helpers.h>
-#include <lockfile.h>
-#include <trace_helpers.h>
-#include <wx/snglinst.h>
-#include <view/view.h>
-#include <tool/tool_manager.h>
-#include <tool/action_manager.h>
-#include <tool/tool_dispatcher.h>
-#include <tool/actions.h>
-#include <ws_draw_item.h>
-#include <page_info.h>
-#include <title_block.h>
-#include <tool/tool_menu.h>
-#include <tool/selection_conditions.h>
-#include <tool/zoom_menu.h>
-#include <tool/grid_menu.h>
-#include <tool/common_tools.h>
 #include <dialog_shim.h>
+#include <eda_draw_frame.h>
+#include <fctsys.h>
 #include <filehistory.h>
+#include <id.h>
+#include <kiface_i.h>
+#include <lockfile.h>
+#include <macros.h>
+#include <msgpanel.h>
+#include <page_info.h>
+#include <pgm_base.h>
+#include <settings/app_settings.h>
+#include <settings/color_settings.h>
+#include <settings/common_settings.h>
+#include <settings/settings_manager.h>
+#include <title_block.h>
+#include <tool/action_manager.h>
+#include <tool/actions.h>
+#include <tool/common_tools.h>
+#include <tool/grid_menu.h>
+#include <tool/selection_conditions.h>
+#include <tool/tool_dispatcher.h>
+#include <tool/tool_manager.h>
+#include <tool/tool_menu.h>
+#include <tool/zoom_menu.h>
+#include <trace_helpers.h>
+#include <view/view.h>
+#include <ws_draw_item.h>
+#include <wx/snglinst.h>
 
 
-///@{
-/// \ingroup config
-static const wxChar FirstRunShownKeyword[] =        wxT( "FirstRunShown" );
-
-static const wxChar FindReplaceFlagsEntry[] =       wxT( "LastFindReplaceFlags" );
-static const wxChar FindStringEntry[] =             wxT( "LastFindString" );
-static const wxChar ReplaceStringEntry[] =          wxT( "LastReplaceString" );
-static const wxChar FindStringHistoryEntry[] =      wxT( "FindStringHistoryList%d" );
-static const wxChar ReplaceStringHistoryEntry[] =   wxT( "ReplaceStringHistoryList%d" );
-///@}
-
 #define FR_HISTORY_LIST_CNT     10   ///< Maximum size of the find/replace history stacks.
 
-/**
- * Integer to set the maximum number of undo items on the stack. If zero,
- * undo items are unlimited.
- *
- * Present as:
- *
- * - SchematicFrameDevelMaxUndoItems (file: eeschema)
- * - LibeditFrameDevelMaxUndoItems (file: eeschema)
- * - PcbFrameDevelMaxUndoItems (file: pcbnew)
- * - ModEditFrameDevelMaxUndoItems (file: pcbnew)
- *
- * \ingroup develconfig
- */
-static const wxString MaxUndoItemsEntry(wxT( "DevelMaxUndoItems" ) );
 
 EDA_DRAW_FRAME::EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType,
                                 const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
@@ -217,26 +196,17 @@ void EDA_DRAW_FRAME::CommonSettingsChanged( bool aEnvVarsChanged )
 {
     EDA_BASE_FRAME::CommonSettingsChanged( aEnvVarsChanged );
 
-    wxConfigBase*         settings = Pgm().CommonSettings();
+    COMMON_SETTINGS*      settings = Pgm().GetCommonSettings();
     KIGFX::VIEW_CONTROLS* viewControls = GetCanvas()->GetViewControls();
 
-    int autosaveInterval;
-    settings->Read( AUTOSAVE_INTERVAL_KEY, &autosaveInterval );
-    SetAutoSaveInterval( autosaveInterval );
+    SetAutoSaveInterval( settings->m_System.autosave_interval );
 
-    int historySize;
-    settings->Read( FILE_HISTORY_SIZE_KEY, &historySize, DEFAULT_FILE_HISTORY_SIZE );
+    int historySize = settings->m_System.file_history_size;
     Kiface().GetFileHistory().SetMaxFiles( (unsigned) std::max( 0, historySize ) );
 
-    bool option;
-    settings->Read( ENBL_MOUSEWHEEL_PAN_KEY, &option );
-    viewControls->EnableMousewheelPan( option );
-
-    settings->Read( ENBL_ZOOM_NO_CENTER_KEY, &option );
-    viewControls->EnableCursorWarping( !option );
-
-    settings->Read( ENBL_AUTO_PAN_KEY, &option );
-    viewControls->EnableAutoPan( option );
+    viewControls->EnableMousewheelPan( settings->m_Input.mousewheel_pan );
+    viewControls->EnableCursorWarping( settings->m_Input.center_on_zoom );
+    viewControls->EnableAutoPan( settings->m_Input.auto_pan );
 
     m_galDisplayOptions.ReadCommonConfig( *settings, this );
 }
@@ -457,102 +427,73 @@ const wxString EDA_DRAW_FRAME::GetZoomLevelIndicator() const
 }
 
 
-void EDA_DRAW_FRAME::LoadSettings( wxConfigBase* aCfg )
+void EDA_DRAW_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_BASE_FRAME::LoadSettings( aCfg );
 
-    wxString baseCfgName = ConfigBaseName();
-    wxConfigBase* cmnCfg = Pgm().CommonSettings();
+    wxString         baseCfgName = ConfigBaseName();
+    COMMON_SETTINGS* cmnCfg      = Pgm().GetCommonSettings();
+    WINDOW_SETTINGS* window      = GetWindowSettings( aCfg );
 
     // Read units used in dialogs and toolbars
-    EDA_UNITS unitsTmp;
-
-    if( aCfg->Read( baseCfgName + UserUnitsEntryKeyword, (int*) &unitsTmp ) )
-        SetUserUnits( unitsTmp );
-    else
-        SetUserUnits( EDA_UNITS::MILLIMETRES );
+    SetUserUnits( static_cast<EDA_UNITS>( aCfg->m_System.units ) );
 
     // Read show/hide grid entry
-    bool btmp;
-    if( aCfg->Read( baseCfgName + ShowGridEntryKeyword, &btmp ) )
-        SetGridVisibility( btmp );
+    SetGridVisibility( window->grid.show );
 
-    aCfg->Read( baseCfgName + LastGridSizeIdKeyword, &m_LastGridSizeId, m_LastGridSizeId );
+    m_LastGridSizeId = window->grid.last_size;
 
     // m_LastGridSizeId is an offset, expected to be >= 0
     if( m_LastGridSizeId < 0 )
         m_LastGridSizeId = 0;
 
-    m_UndoRedoCountMax = aCfg->Read( baseCfgName + MaxUndoItemsEntry,
-                                     long( DEFAULT_MAX_UNDO_ITEMS ) );
+    m_UndoRedoCountMax = aCfg->m_System.max_undo_items;
+    m_firstRunDialogSetting = aCfg->m_System.first_run_shown;
 
-    aCfg->Read( baseCfgName + FirstRunShownKeyword, &m_firstRunDialogSetting, 0L );
+    m_galDisplayOptions.ReadConfig( *cmnCfg, *window, this );
 
-    m_galDisplayOptions.ReadConfig( *cmnCfg, *aCfg, baseCfgName, this );
+    m_findReplaceData->SetFlags( aCfg->m_FindReplace.flags );
+    m_findReplaceData->SetFindString( aCfg->m_FindReplace.find_string );
+    m_findReplaceData->SetReplaceString( aCfg->m_FindReplace.replace_string );
 
-    long tmp;
-    aCfg->Read( FindReplaceFlagsEntry, &tmp, (long) wxFR_DOWN );
-    m_findReplaceData->SetFlags( (wxUint32) tmp & ~FR_REPLACE_ITEM_FOUND );
-    m_findReplaceData->SetFindString( aCfg->Read( FindStringEntry, wxEmptyString ) );
-    m_findReplaceData->SetReplaceString( aCfg->Read( ReplaceStringEntry, wxEmptyString ) );
+    for( auto& s : aCfg->m_FindReplace.find_history )
+        m_findStringHistoryList.Add( s );
 
-    // Load the find and replace string history list.
-    for( int i = 0; i < FR_HISTORY_LIST_CNT; ++i )
-    {
-        wxString tmpHistory;
-        wxString entry;
-        entry.Printf( FindStringHistoryEntry, i );
-        tmpHistory = aCfg->Read( entry, wxEmptyString );
-
-        if( !tmpHistory.IsEmpty() )
-            m_findStringHistoryList.Add( tmpHistory );
-
-        entry.Printf( ReplaceStringHistoryEntry, i );
-        tmpHistory = aCfg->Read( entry, wxEmptyString );
-
-        if( !tmpHistory.IsEmpty() )
-            m_replaceStringHistoryList.Add( tmpHistory );
-    }
+    for( auto& s : aCfg->m_FindReplace.replace_history )
+        m_replaceStringHistoryList.Add( s );
 }
 
 
-void EDA_DRAW_FRAME::SaveSettings( wxConfigBase* aCfg )
+void EDA_DRAW_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_BASE_FRAME::SaveSettings( aCfg );
 
-    wxString baseCfgName = ConfigBaseName();
+    WINDOW_SETTINGS* window = GetWindowSettings( aCfg );
 
-    aCfg->Write( baseCfgName + UserUnitsEntryKeyword, (int) m_userUnits );
-    aCfg->Write( baseCfgName + ShowGridEntryKeyword, IsGridVisible() );
-    aCfg->Write( baseCfgName + LastGridSizeIdKeyword, ( long ) m_LastGridSizeId );
-    aCfg->Write( baseCfgName + FirstRunShownKeyword, m_firstRunDialogSetting );
+    aCfg->m_System.units = static_cast<int>( m_userUnits );
+    aCfg->m_System.first_run_shown = m_firstRunDialogSetting;
+
+    window->grid.show = IsGridVisible();
+    window->grid.last_size = m_LastGridSizeId;
 
     if( GetScreen() )
-        aCfg->Write( baseCfgName + MaxUndoItemsEntry, long( GetScreen()->GetMaxUndoItems() ) );
+        aCfg->m_System.max_undo_items = GetScreen()->GetMaxUndoItems();
 
-    m_galDisplayOptions.WriteConfig( *aCfg, baseCfgName );
+    m_galDisplayOptions.WriteConfig( *window );
 
-    // Save find dialog session setting.
-    aCfg->Write( FindReplaceFlagsEntry, (long) m_findReplaceData->GetFlags() );
-    aCfg->Write( FindStringEntry, m_findReplaceData->GetFindString() );
-    aCfg->Write( ReplaceStringEntry, m_findReplaceData->GetReplaceString() );
+    aCfg->m_FindReplace.flags = m_findReplaceData->GetFlags();
+    aCfg->m_FindReplace.find_string = m_findReplaceData->GetFindString();
+    aCfg->m_FindReplace.replace_string = m_findReplaceData->GetReplaceString();
 
-    // Save the find and replace string history list.
-    unsigned i;
-    wxString tmpHistory;
-    wxString entry;     // invoke constructor outside of any loops
+    aCfg->m_FindReplace.find_history.clear();
+    aCfg->m_FindReplace.replace_history.clear();
 
-    for( i = 0; i < m_findStringHistoryList.GetCount() && i < FR_HISTORY_LIST_CNT; i++ )
-    {
-        entry.Printf( FindStringHistoryEntry, i );
-        aCfg->Write( entry, m_findStringHistoryList[ i ] );
-    }
+    for( size_t i = 0; i < m_findStringHistoryList.GetCount() && i < FR_HISTORY_LIST_CNT; i++ )
+        aCfg->m_FindReplace.find_history.push_back( m_findStringHistoryList[ i ].ToStdString() );
 
-    for( i = 0; i < m_replaceStringHistoryList.GetCount() && i < FR_HISTORY_LIST_CNT; i++ )
-    {
-        entry.Printf( ReplaceStringHistoryEntry, i );
-        aCfg->Write( entry, m_replaceStringHistoryList[ i ] );
-    }
+    for( size_t i = 0; i < m_replaceStringHistoryList.GetCount() && i < FR_HISTORY_LIST_CNT; i++ )
+        aCfg->m_FindReplace.replace_history.push_back(
+                m_replaceStringHistoryList[ i ].ToStdString() );
 }
 
 
@@ -618,13 +559,10 @@ void EDA_DRAW_FRAME::SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType )
 EDA_DRAW_PANEL_GAL::GAL_TYPE EDA_DRAW_FRAME::LoadCanvasTypeSetting()
 {
     EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE;
-    wxConfigBase* cfg = Kiface().KifaceSettings();
+    APP_SETTINGS_BASE* cfg = Kiface().KifaceSettings();
 
     if( cfg )
-    {
-        canvasType = (EDA_DRAW_PANEL_GAL::GAL_TYPE)
-                          cfg->ReadLong( GetCanvasTypeKey(), EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE );
-    }
+        canvasType = static_cast<EDA_DRAW_PANEL_GAL::GAL_TYPE>( cfg->m_Graphics.canvas_type );
 
     if( canvasType < EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE
             || canvasType >= EDA_DRAW_PANEL_GAL::GAL_TYPE_LAST )
@@ -682,10 +620,12 @@ bool EDA_DRAW_FRAME::saveCanvasTypeSetting( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvas
         return false;
     }
 
-    wxConfigBase* cfg = Kiface().KifaceSettings();
+    APP_SETTINGS_BASE* cfg = Kiface().KifaceSettings();
 
     if( cfg )
-        return cfg->Write( GetCanvasTypeKey(), (long) aCanvasType );
+        cfg->m_Graphics.canvas_type = static_cast<int>( aCanvasType );
+
+    Pgm().GetSettingsManager().Save( cfg );
 
     return false;
 }
@@ -862,3 +802,9 @@ void EDA_DRAW_FRAME::RecreateToolbars()
     // Update the checked state of tools
     SyncToolbars();
 }
+
+
+COLOR4D EDA_DRAW_FRAME::GetLayerColor( SCH_LAYER_ID aLayer )
+{
+    return Pgm().GetSettingsManager().GetColorSettings()->GetColor( aLayer );
+}
diff --git a/common/filehistory.cpp b/common/filehistory.cpp
index ddba8e96d6..f89374a0d7 100644
--- a/common/filehistory.cpp
+++ b/common/filehistory.cpp
@@ -24,6 +24,7 @@
 
 #include <filehistory.h>
 #include <id.h>
+#include <settings/app_settings.h>
 #include <tool/action_menu.h>
 #include <tool/selection_conditions.h>
 #include <wx/menu.h>
@@ -39,6 +40,45 @@ FILE_HISTORY::FILE_HISTORY( size_t aMaxFiles, int aBaseFileId ) :
 }
 
 
+void FILE_HISTORY::Load( const APP_SETTINGS_BASE& aSettings )
+{
+    m_fileHistory.clear();
+
+    // file_history stores the most recent file first
+    for( auto it = aSettings.m_System.file_history.rbegin();
+         it != aSettings.m_System.file_history.rend(); ++it )
+        AddFileToHistory( *it );
+}
+
+
+void FILE_HISTORY::Load( const std::vector<wxString>& aList )
+{
+    m_fileHistory.clear();
+
+    for( const auto& file : aList )
+        AddFileToHistory( file );
+}
+
+
+void FILE_HISTORY::Save( APP_SETTINGS_BASE& aSettings )
+{
+    aSettings.m_System.file_history.clear();
+
+    for( const auto& file : m_fileHistory )
+        aSettings.m_System.file_history.insert( aSettings.m_System.file_history.begin(),
+                                                file.ToStdString() );
+}
+
+
+void FILE_HISTORY::Save( std::vector<wxString>* aList )
+{
+    aList->clear();
+
+    for( const auto& file : m_fileHistory )
+        aList->push_back( file );
+}
+
+
 void FILE_HISTORY::SetMaxFiles( size_t aMaxFiles )
 {
     m_fileMaxFiles = std::min( aMaxFiles, (size_t) MAX_FILE_HISTORY_SIZE );
diff --git a/common/fp_lib_table.cpp b/common/fp_lib_table.cpp
index 406b5bba8a..01364a6851 100644
--- a/common/fp_lib_table.cpp
+++ b/common/fp_lib_table.cpp
@@ -25,13 +25,13 @@
 
 
 #include <fctsys.h>
-#include <common.h>
 #include <kiface_i.h>
 #include <footprint_info.h>
 #include <lib_id.h>
 #include <lib_table_lexer.h>
 #include <pgm_base.h>
 #include <search_stack.h>
+#include <settings/settings_manager.h>
 #include <systemdirsappend.h>
 #include <fp_lib_table.h>
 #include <class_module.h>
@@ -513,7 +513,7 @@ wxString FP_LIB_TABLE::GetGlobalTableFileName()
 {
     wxFileName fn;
 
-    fn.SetPath( GetKicadConfigPath() );
+    fn.SetPath( SETTINGS_MANAGER::GetUserSettingsPath() );
     fn.SetName( global_tbl_name );
 
     return fn.GetFullPath();
diff --git a/common/gal/color4d.cpp b/common/gal/color4d.cpp
index eadc3c2206..e31b2eadb2 100644
--- a/common/gal/color4d.cpp
+++ b/common/gal/color4d.cpp
@@ -24,7 +24,7 @@
  */
 
 #include <map>
-
+#include <nlohmann/json.hpp>
 #include <gal/color4d.h>
 
 using namespace KIGFX;
@@ -146,6 +146,17 @@ std::ostream &operator<<( std::ostream &aStream, COLOR4D const &aColor )
     return aStream << aColor.ToWxString( wxC2S_CSS_SYNTAX );
 }
 
+void to_json( nlohmann::json& aJson, const COLOR4D& aColor )
+{
+    aJson = nlohmann::json( aColor.ToWxString( wxC2S_CSS_SYNTAX ).ToStdString() );
+}
+
+
+void from_json( const nlohmann::json& aJson, COLOR4D& aColor )
+{
+    aColor.SetFromWxString( aJson.get<std::string>() );
+}
+
 }
 
 
diff --git a/common/gal/gal_display_options.cpp b/common/gal/gal_display_options.cpp
index 3acb173ca5..7cb2d4d711 100644
--- a/common/gal/gal_display_options.cpp
+++ b/common/gal/gal_display_options.cpp
@@ -22,27 +22,16 @@
 */
 
 #include <gal/gal_display_options.h>
+#include <settings/app_settings.h>
+#include <settings/common_settings.h>
 
-#include <wx/config.h>
 #include <wx/log.h>
 
 #include <config_map.h>
 #include <dpi_scaling.h>
-#include <pgm_base.h>
 
 using namespace KIGFX;
 
-/*
- * Config option strings
- */
-static const wxString GalGridStyleConfig( "GridStyle" );
-static const wxString GalGridLineWidthConfig( "GridLineWidth" );
-static const wxString GalGridMaxDensityConfig( "GridMaxDensity" );
-static const wxString GalGridAxesEnabledConfig( "GridAxesEnabled" );
-static const wxString GalFullscreenCursorConfig( "CursorFullscreen" );
-static const wxString GalForceDisplayCursorConfig( "ForceDisplayCursor" );
-
-
 static const UTIL::CFG_MAP<KIGFX::GRID_STYLE> gridStyleConfigVals =
 {
     { KIGFX::GRID_STYLE::DOTS,       0 },
@@ -74,43 +63,34 @@ GAL_DISPLAY_OPTIONS::GAL_DISPLAY_OPTIONS()
 {}
 
 
-void GAL_DISPLAY_OPTIONS::ReadAppConfig( wxConfigBase& aCfg, const wxString& aBaseName )
+void GAL_DISPLAY_OPTIONS::ReadWindowSettings( WINDOW_SETTINGS& aCfg )
 {
-    const wxString baseName = aBaseName + GAL_DISPLAY_OPTIONS_KEY;
+    wxLogTrace( traceGalDispOpts, "Reading app-specific options" );
 
-    wxLogTrace( traceGalDispOpts, "Reading options with base name '%s'", baseName );
+    m_gridStyle = UTIL::GetValFromConfig( gridStyleConfigVals, aCfg.grid.style );
+    m_gridLineWidth = aCfg.grid.line_width;
+    m_gridMinSpacing = aCfg.grid.min_spacing;
+    m_axesEnabled = aCfg.grid.axes_enabled;
 
-    long readLong; // Temp value buffer
-
-    aCfg.Read( baseName + GalGridStyleConfig, &readLong,
-            static_cast<long>( KIGFX::GRID_STYLE::DOTS ) );
-    m_gridStyle = UTIL::GetValFromConfig( gridStyleConfigVals, readLong );
-
-    aCfg.Read( baseName + GalGridLineWidthConfig, &m_gridLineWidth, 1.0 );
-    aCfg.Read( baseName + GalGridMaxDensityConfig, &m_gridMinSpacing, 10 );
-    aCfg.Read( baseName + GalGridAxesEnabledConfig, &m_axesEnabled, false );
-    aCfg.Read( baseName + GalFullscreenCursorConfig, &m_fullscreenCursor, false );
-    aCfg.Read( baseName + GalForceDisplayCursorConfig, &m_forceDisplayCursor, true );
+    m_fullscreenCursor = aCfg.cursor.fullscreen_cursor;
+    m_forceDisplayCursor = aCfg.cursor.always_show_cursor;
 
     NotifyChanged();
 }
 
 
-void GAL_DISPLAY_OPTIONS::ReadCommonConfig( wxConfigBase& aCommonConfig, wxWindow* aWindow )
+void GAL_DISPLAY_OPTIONS::ReadCommonConfig( COMMON_SETTINGS& aSettings, wxWindow* aWindow )
 {
     wxLogTrace( traceGalDispOpts, "Reading common config" );
 
-    int temp;
-    aCommonConfig.Read(
-            GAL_ANTIALIASING_MODE_KEY, &temp, (int) KIGFX::OPENGL_ANTIALIASING_MODE::NONE );
-    gl_antialiasing_mode = (KIGFX::OPENGL_ANTIALIASING_MODE) temp;
+    gl_antialiasing_mode = static_cast<KIGFX::OPENGL_ANTIALIASING_MODE>(
+            aSettings.m_Graphics.opengl_aa_mode );
 
-    aCommonConfig.Read(
-            CAIRO_ANTIALIASING_MODE_KEY, &temp, (int) KIGFX::CAIRO_ANTIALIASING_MODE::NONE );
-    cairo_antialiasing_mode = (KIGFX::CAIRO_ANTIALIASING_MODE) temp;
+    cairo_antialiasing_mode = static_cast<KIGFX::CAIRO_ANTIALIASING_MODE>(
+            aSettings.m_Graphics.cairo_aa_mode );
 
     {
-        const DPI_SCALING dpi{ &aCommonConfig, aWindow };
+        const DPI_SCALING dpi{ &aSettings, aWindow };
         m_scaleFactor = dpi.GetScaleFactor();
     }
 
@@ -118,31 +98,27 @@ void GAL_DISPLAY_OPTIONS::ReadCommonConfig( wxConfigBase& aCommonConfig, wxWindo
 }
 
 
-void GAL_DISPLAY_OPTIONS::ReadConfig( wxConfigBase& aCommonConfig, wxConfigBase& aAppConfig,
-        const wxString& aBaseCfgName, wxWindow* aWindow )
+void GAL_DISPLAY_OPTIONS::ReadConfig( COMMON_SETTINGS& aCommonConfig,
+                                      WINDOW_SETTINGS& aWindowConfig, wxWindow* aWindow )
 {
-    wxLogTrace( traceGalDispOpts, "Reading common and app config (%s)", aBaseCfgName );
+    wxLogTrace( traceGalDispOpts, "Reading common and app config" );
 
-    ReadAppConfig( aAppConfig, aBaseCfgName );
+    ReadWindowSettings( aWindowConfig );
 
     ReadCommonConfig( aCommonConfig, aWindow );
 }
 
 
-void GAL_DISPLAY_OPTIONS::WriteConfig( wxConfigBase& aCfg, const wxString& aBaseName )
+void GAL_DISPLAY_OPTIONS::WriteConfig( WINDOW_SETTINGS& aCfg )
 {
-    const wxString baseName = aBaseName + GAL_DISPLAY_OPTIONS_KEY;
+    wxLogTrace( traceGalDispOpts, "Writing window settings" );
 
-    wxLogTrace( traceGalDispOpts, "Writing app config (%s)", baseName );
-
-    aCfg.Write( baseName + GalGridStyleConfig,
-                 UTIL::GetConfigForVal( gridStyleConfigVals, m_gridStyle ) );
-
-    aCfg.Write( baseName + GalGridLineWidthConfig, m_gridLineWidth );
-    aCfg.Write( baseName + GalGridMaxDensityConfig, m_gridMinSpacing );
-    aCfg.Write( baseName + GalGridAxesEnabledConfig, m_axesEnabled );
-    aCfg.Write( baseName + GalFullscreenCursorConfig, m_fullscreenCursor );
-    aCfg.Write( baseName + GalForceDisplayCursorConfig, m_forceDisplayCursor );
+    aCfg.grid.style = UTIL::GetConfigForVal( gridStyleConfigVals, m_gridStyle );
+    aCfg.grid.line_width = m_gridLineWidth;
+    aCfg.grid.min_spacing = m_gridMinSpacing;
+    aCfg.grid.axes_enabled = m_axesEnabled;
+    aCfg.cursor.fullscreen_cursor = m_fullscreenCursor;
+    aCfg.cursor.always_show_cursor = m_forceDisplayCursor;
 }
 
 
diff --git a/common/hotkeys_basic.cpp b/common/hotkeys_basic.cpp
index e1c0ff2794..20dc67e394 100644
--- a/common/hotkeys_basic.cpp
+++ b/common/hotkeys_basic.cpp
@@ -34,6 +34,7 @@
 #include <macros.h>
 #include <menus_helpers.h>
 #include <eda_draw_frame.h>
+#include <settings/settings_manager.h>
 
 #include <tool/tool_manager.h>
 #include "dialogs/dialog_hotkey_list.h"
@@ -314,7 +315,7 @@ void ReadHotKeyConfig( wxString fileName, std::map<std::string, int>& aHotKeys )
     {
         wxFileName fn( "user" );
         fn.SetExt( DEFAULT_HOTKEY_FILENAME_EXT );
-        fn.SetPath( GetKicadConfigPath() );
+        fn.SetPath( SETTINGS_MANAGER::GetUserSettingsPath() );
         fileName = fn.GetFullPath();
     }
     
@@ -350,7 +351,7 @@ int WriteHotKeyConfig( const std::map<std::string, TOOL_ACTION*>& aActionMap )
     wxFileName fn( "user" );
 
     fn.SetExt( DEFAULT_HOTKEY_FILENAME_EXT );
-    fn.SetPath( GetKicadConfigPath() );
+    fn.SetPath( SETTINGS_MANAGER::GetUserSettingsPath() );
 
     // Read the existing config (all hotkeys)
     //
@@ -394,7 +395,7 @@ int ReadLegacyHotkeyConfigFile( const wxString& aFilename, std::map<std::string,
     wxFileName fn( aFilename );
 
     fn.SetExt( DEFAULT_HOTKEY_FILENAME_EXT );
-    fn.SetPath( GetKicadConfigPath() );
+    fn.SetPath( SETTINGS_MANAGER::GetUserSettingsPath() );
 
     if( !wxFile::Exists( fn.GetFullPath() ) )
         return 0;
diff --git a/common/kiface_i.cpp b/common/kiface_i.cpp
index 8c0abe798e..7ca98ac2cd 100644
--- a/common/kiface_i.cpp
+++ b/common/kiface_i.cpp
@@ -24,7 +24,6 @@
  */
 
 #include <macros.h>             // FROM_UTF8()
-#include <wx/config.h>
 #include <wx/stdpaths.h>
 
 #include <kiface_i.h>
diff --git a/common/lib_table_base.cpp b/common/lib_table_base.cpp
index 0b7da9633c..01bca9af44 100644
--- a/common/lib_table_base.cpp
+++ b/common/lib_table_base.cpp
@@ -29,12 +29,13 @@
 
 #include <set>
 
-#include <fctsys.h>
 #include <common.h>
-#include <macros.h>
+#include <fctsys.h>
 #include <kiface_i.h>
-#include <lib_table_lexer.h>
 #include <lib_table_base.h>
+#include <lib_table_lexer.h>
+#include <macros.h>
+#include <settings/app_settings.h>
 
 
 #define OPT_SEP     '|'         ///< options separator character
diff --git a/common/lib_tree_model_adapter.cpp b/common/lib_tree_model_adapter.cpp
index ae9706364c..9b6c357992 100644
--- a/common/lib_tree_model_adapter.cpp
+++ b/common/lib_tree_model_adapter.cpp
@@ -24,6 +24,7 @@
 #include <kiface_i.h>
 #include <config_params.h>
 #include <lib_tree_model_adapter.h>
+#include <settings/app_settings.h>
 #include <wx/tokenzr.h>
 #include <wx/wupdlock.h>
 
@@ -87,14 +88,8 @@ LIB_TREE_MODEL_ADAPTER::LIB_TREE_MODEL_ADAPTER( EDA_BASE_FRAME* aParent ) :
     m_colWidths[PART_COL] = 360;
     m_colWidths[DESC_COL] = 2000;
 
-    m_config = Kiface().KifaceSettings();
-    m_configPrefix = typeid( this ).name();
-
-    // Read the column width from the global config
-    int colWidth = 0;
-
-    if( m_config->Read( m_configPrefix + LIST_COLUMN_WIDTH_KEY, &colWidth ) )
-        m_colWidths[PART_COL] = colWidth;
+    auto cfg = Kiface().KifaceSettings();
+    m_colWidths[PART_COL] = cfg->m_LibTree.column_width;
 
     // Read the pinned entries from the project config
     m_parent->Kiway().Prj().ConfigLoad( Kiface().KifaceSearch(), m_parent->GetName(),
@@ -110,8 +105,8 @@ void LIB_TREE_MODEL_ADAPTER::SaveColWidths()
 {
     if( m_widget )
     {
-        int colWidth = m_widget->GetColumn( PART_COL )->GetWidth();
-        m_config->Write( m_configPrefix + LIST_COLUMN_WIDTH_KEY, colWidth );
+        auto cfg = Kiface().KifaceSettings();
+        cfg->m_LibTree.column_width = m_widget->GetColumn( PART_COL )->GetWidth();
     }
     else
     {
diff --git a/common/lib_tree_model_adapter.h b/common/lib_tree_model_adapter.h
index b9aef9bba5..f06ad68189 100644
--- a/common/lib_tree_model_adapter.h
+++ b/common/lib_tree_model_adapter.h
@@ -89,6 +89,7 @@
  * - `HasDefaultCompare()` - whether sorted by default
  */
 
+class APP_SETTINGS_BASE;
 class TOOL_INTERACTIVE;
 class PARAM_CFG;
 
@@ -359,8 +360,6 @@ private:
     wxDataViewColumn*       m_col_desc;
     wxDataViewCtrl*         m_widget;
 
-    wxConfigBase*           m_config;
-    wxString                m_configPrefix;
     std::vector<PARAM_CFG*> m_projectFileParams;
 
     int                     m_colWidths[NUM_COLS];
diff --git a/common/page_layout/ws_painter.cpp b/common/page_layout/ws_painter.cpp
index 2ffeec787d..c30ea666ef 100644
--- a/common/page_layout/ws_painter.cpp
+++ b/common/page_layout/ws_painter.cpp
@@ -31,6 +31,7 @@
 #include <eda_draw_frame.h>
 #include <title_block.h>
 #include <build_version.h>
+#include <settings/color_settings.h>
 #include <ws_draw_item.h>
 #include <gal/graphics_abstraction_layer.h>
 
@@ -52,6 +53,18 @@ WS_RENDER_SETTINGS::WS_RENDER_SETTINGS()
 }
 
 
+void WS_RENDER_SETTINGS::LoadColors( const COLOR_SETTINGS* aSettings )
+{
+    for( int layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; layer ++)
+        m_layerColors[ layer ] = aSettings->GetColor( layer );
+
+    for( int layer = GAL_LAYER_ID_START; layer < GAL_LAYER_ID_END; layer ++)
+        m_layerColors[ layer ] = aSettings->GetColor( layer );
+
+    m_backgroundColor = aSettings->GetColor( LAYER_SCHEMATIC_BACKGROUND );
+}
+
+
 const COLOR4D& WS_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
 {
     const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
diff --git a/common/page_layout/ws_proxy_view_item.cpp b/common/page_layout/ws_proxy_view_item.cpp
index d614d5489e..5ebd4d2a70 100644
--- a/common/page_layout/ws_proxy_view_item.cpp
+++ b/common/page_layout/ws_proxy_view_item.cpp
@@ -41,7 +41,8 @@ WS_PROXY_VIEW_ITEM::WS_PROXY_VIEW_ITEM( int aMils2IUscalefactor, const PAGE_INFO
         m_titleBlock( aTitleBlock ),
         m_pageInfo( aPageInfo ),
         m_sheetNumber( 1 ),
-        m_sheetCount( 1 )
+        m_sheetCount( 1 ),
+        m_colorLayer( LAYER_WORKSHEET )
 {
 }
 
@@ -110,7 +111,7 @@ void WS_PROXY_VIEW_ITEM::ViewDraw( int aLayer, VIEW* aView ) const
     WS_PAINTER   ws_painter( gal );
     WS_RENDER_SETTINGS* ws_settings =static_cast<WS_RENDER_SETTINGS*>( ws_painter.GetSettings() );
 
-    ws_settings->SetNormalColor( settings->GetLayerColor( LAYER_WORKSHEET ) );
+    ws_settings->SetNormalColor( settings->GetLayerColor( m_colorLayer ) );
     ws_settings->SetSelectedColor( settings->GetLayerColor( LAYER_SELECT_OVERLAY ) );
     ws_settings->SetBrightenedColor( settings->GetLayerColor( LAYER_BRIGHTENED ) );
 
diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp
index 28d71788b0..df2ea60161 100644
--- a/common/pgm_base.cpp
+++ b/common/pgm_base.cpp
@@ -40,32 +40,26 @@
 #include <wx/sysopt.h>
 #include <wx/richmsgdlg.h>
 
-#include <pgm_base.h>
-#include <eda_draw_frame.h>
-#include <eda_base_frame.h>
-#include <macros.h>
-#include <config_params.h>
-#include <id.h>
 #include <build_version.h>
-#include <hotkeys_basic.h>
-#include <gestfich.h>
-#include <menus_helpers.h>
+#include <config_params.h>
 #include <confirm.h>
 #include <dialog_configure_paths.h>
+#include <eda_base_frame.h>
+#include <eda_draw_frame.h>
+#include <gal/gal_display_options.h>
+#include <gestfich.h>
+#include <hotkeys_basic.h>
+#include <id.h>
 #include <lockfile.h>
+#include <macros.h>
+#include <menus_helpers.h>
+#include <pgm_base.h>
+#include <settings/common_settings.h>
+#include <settings/settings_manager.h>
 #include <systemdirsappend.h>
 #include <trace_helpers.h>
-#include <gal/gal_display_options.h>
 
-#define KICAD_COMMON                     wxT( "kicad_common" )
 
-// some key strings used to store parameters in KICAD_COMMON
-
-const wxChar PGM_BASE::workingDirKey[] = wxT( "WorkingDir" );     // public
-
-static const wxChar languageCfgKey[]   = wxT( "LanguageID" );
-static const wxChar pathEnvVariables[] = wxT( "EnvironmentVariables" );
-static const wxChar showEnvVarWarningDialog[] = wxT( "ShowEnvVarWarningDialog" );
 static const wxChar traceEnvVars[]     = wxT( "KIENVVARS" );
 
 
@@ -133,8 +127,6 @@ PGM_BASE::~PGM_BASE()
 void PGM_BASE::Destroy()
 {
     // unlike a normal destructor, this is designed to be called more than once safely:
-    m_common_settings.reset();
-
     delete m_pgm_checker;
     m_pgm_checker = 0;
 
@@ -153,8 +145,8 @@ wxApp& PGM_BASE::App()
 void PGM_BASE::SetEditorName( const wxString& aFileName )
 {
     m_editor_name = aFileName;
-    wxASSERT( m_common_settings );
-    m_common_settings->Write( "Editor", aFileName );
+    wxASSERT( GetCommonSettings() );
+    GetCommonSettings()->m_System.editor_name = aFileName;
 }
 
 
@@ -222,8 +214,6 @@ bool PGM_BASE::InitPgm()
 {
     wxFileName pgm_name( App().argv[0] );
 
-    wxConfigBase::DontCreateOnDemand();
-
     wxInitAllImageHandlers();
 
     m_pgm_checker = new wxSingleInstanceChecker( pgm_name.GetName().Lower() + wxT( "-" ) +
@@ -240,6 +230,12 @@ bool PGM_BASE::InitPgm()
             return false;
     }
 
+    m_settings_manager = std::unique_ptr<SETTINGS_MANAGER>( new SETTINGS_MANAGER );
+
+    // Something got in the way of settings load: can't continue
+    if( !m_settings_manager->IsOK() )
+        return false;
+
     // Init KiCad environment
     // the environment variable KICAD (if exists) gives the kicad path:
     // something like set KICAD=d:\kicad
@@ -274,9 +270,6 @@ bool PGM_BASE::InitPgm()
 
     SetLanguagePath();
 
-    // OS specific instantiation of wxConfigBase derivative:
-    m_common_settings = GetNewConfig( KICAD_COMMON );
-
     wxString envVarName = wxT( "KIGITHUB" );
     ENV_VAR_ITEM envVarItem;
     wxString envValue;
@@ -433,7 +426,7 @@ bool PGM_BASE::InitPgm()
     envVarItem.SetValue( tmpFileName.GetPath() );
     m_local_env_vars[ envVarName ] = envVarItem;
 
-    ReadPdfBrowserInfos();      // needs m_common_settings
+    GetSettingsManager().Load( GetCommonSettings() );
 
     // Init user language *before* calling loadCommonSettings, because
     // env vars could be incorrectly initialized on Linux
@@ -442,6 +435,8 @@ bool PGM_BASE::InitPgm()
 
     loadCommonSettings();
 
+    ReadPdfBrowserInfos();      // needs GetCommonSettings()
+
 #ifdef __WXMAC__
     // Always show filters on Open dialog to be able to choose plugin
     wxSystemOptions::SetOption( wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1 );
@@ -495,141 +490,65 @@ bool PGM_BASE::setExecutablePath()
 
 void PGM_BASE::loadCommonSettings()
 {
-    wxASSERT( m_common_settings );
-
     m_help_size.x = 500;
     m_help_size.y = 400;
 
-    // This only effect the first time KiCad is run.  The user's setting will be used for all
-    // subsequent runs.  Menu icons are off by default on OSX and on for all other platforms.
-#if defined( __WXMAC__ )
-    bool defaultUseIconsInMenus = false;
-#else
-    bool defaultUseIconsInMenus = true;
-#endif
+    m_show_env_var_dialog = GetCommonSettings()->m_Env.show_warning_dialog;
+    m_editor_name = GetCommonSettings()->m_System.editor_name;
 
-    m_common_settings->Read( showEnvVarWarningDialog, &m_show_env_var_dialog );
-
-    if( !m_common_settings->HasEntry( USE_ICONS_IN_MENUS_KEY ) )
-        m_common_settings->Write( USE_ICONS_IN_MENUS_KEY, defaultUseIconsInMenus );
-
-    if( !m_common_settings->HasEntry( ICON_SCALE_KEY )
-        || !m_common_settings->HasEntry( GAL_ANTIALIASING_MODE_KEY )
-        || !m_common_settings->HasEntry( CAIRO_ANTIALIASING_MODE_KEY )  )
+    for( const auto& it : GetCommonSettings()->m_Env.vars )
     {
-        // 5.0 and earlier saved common settings in each app, and saved hardware antialiasing
-        // options only in pcbnew (which was the only canvas to support them).  Since there's
-        // no single right answer to where to pull the common settings from, we might as well
-        // get them along with the hardware antialiasing option from pcbnew.
-        auto pcbnewConfig = GetNewConfig( wxString::FromUTF8( "pcbnew" ) );
-        wxString pcbFrameKey( PCB_EDIT_FRAME_NAME );
-
-        if( !m_common_settings->HasEntry( ICON_SCALE_KEY ) )
-        {
-            int temp;
-            wxString msg;
-            bool option;
-
-            pcbnewConfig->Read( "PcbIconScale", &temp, 0 );
-            m_common_settings->Write( ICON_SCALE_KEY, temp );
-
-            pcbnewConfig->Read( ENBL_MOUSEWHEEL_PAN_KEY, &option, false );
-            m_common_settings->Write( ENBL_MOUSEWHEEL_PAN_KEY, option );
-
-            pcbnewConfig->Read( ENBL_ZOOM_NO_CENTER_KEY, &option, false );
-            m_common_settings->Write( ENBL_ZOOM_NO_CENTER_KEY, option );
-
-            pcbnewConfig->Read( ENBL_AUTO_PAN_KEY, &option, true );
-            m_common_settings->Write( ENBL_AUTO_PAN_KEY, option );
-        }
-
-        if( !m_common_settings->HasEntry( GAL_ANTIALIASING_MODE_KEY ) )
-        {
-            int temp;
-            pcbnewConfig->Read( pcbFrameKey + GAL_DISPLAY_OPTIONS_KEY + GAL_ANTIALIASING_MODE_KEY,
-                                &temp, (int) KIGFX::OPENGL_ANTIALIASING_MODE::NONE );
-            m_common_settings->Write( GAL_ANTIALIASING_MODE_KEY, temp );
-        }
-
-        if( !m_common_settings->HasEntry( CAIRO_ANTIALIASING_MODE_KEY ) )
-        {
-            int temp;
-            pcbnewConfig->Read( pcbFrameKey + GAL_DISPLAY_OPTIONS_KEY + CAIRO_ANTIALIASING_MODE_KEY,
-                                &temp, (int) KIGFX::CAIRO_ANTIALIASING_MODE::NONE );
-            m_common_settings->Write( CAIRO_ANTIALIASING_MODE_KEY, temp );
-        }
-    }
-
-    m_editor_name = m_common_settings->Read( "Editor" );
-
-    wxString entry, oldPath;
-    wxArrayString entries;
-    long index = 0L;
-
-    oldPath = m_common_settings->GetPath();
-    m_common_settings->SetPath( pathEnvVariables );
-
-    while( m_common_settings->GetNextEntry( entry, index ) )
-    {
-        wxLogTrace( traceEnvVars,
-                    "Enumerating over entry %s, %ld.", GetChars( entry ), index );
+        wxString key( it.first.c_str(), wxConvUTF8 );
+        wxLogTrace( traceEnvVars, "Enumerating over entry %s = %s.", key, it.second );
 
         // Do not store the env var PROJECT_VAR_NAME ("KIPRJMOD") definition if for some reason
         // it is found in config. (It is reserved and defined as project path)
-        if( entry == PROJECT_VAR_NAME )
+        if( key == PROJECT_VAR_NAME )
             continue;
 
-        entries.Add( entry );
-    }
-
-    for( unsigned i = 0;  i < entries.GetCount();  i++ )
-    {
-        wxString val = m_common_settings->Read( entries[i], wxEmptyString );
-
-        if( m_local_env_vars[ entries[i] ].GetDefinedExternally() )
+        if( m_local_env_vars[ key ].GetDefinedExternally() )
             continue;
 
-        m_local_env_vars[ entries[i]  ] = ENV_VAR_ITEM( val, wxGetEnv( entries[i], NULL ) );
+        m_local_env_vars[ key ] = ENV_VAR_ITEM( it.second, wxGetEnv( it.first, nullptr ) );
     }
 
-    for( ENV_VAR_MAP_ITER it = m_local_env_vars.begin(); it != m_local_env_vars.end(); ++it )
-    {
-        SetLocalEnvVariable( it->first, it->second.GetValue() );
-    }
-
-    m_common_settings->SetPath( oldPath );
+    for( auto& m_local_env_var : m_local_env_vars )
+        SetLocalEnvVariable( m_local_env_var.first, m_local_env_var.second.GetValue() );
 }
 
 
 void PGM_BASE::SaveCommonSettings()
 {
-    // m_common_settings is not initialized until fairly late in the
+    // GetCommonSettings() is not initialized until fairly late in the
     // process startup: InitPgm(), so test before using:
-    if( m_common_settings )
+    if( GetCommonSettings() )
     {
-        wxString cur_dir = wxGetCwd();
-
-        m_common_settings->Write( workingDirKey, cur_dir );
-        m_common_settings->Write( showEnvVarWarningDialog, m_show_env_var_dialog );
+        GetCommonSettings()->m_System.working_dir = wxGetCwd().ToStdString();
+        GetCommonSettings()->m_Env.show_warning_dialog = m_show_env_var_dialog;
 
         // Save the local environment variables.
-        m_common_settings->SetPath( pathEnvVariables );
-
-        for( ENV_VAR_MAP_ITER it = m_local_env_vars.begin(); it != m_local_env_vars.end(); ++it )
+        for( auto& m_local_env_var : m_local_env_vars )
         {
-            if( it->second.GetDefinedExternally() )
+            if( m_local_env_var.second.GetDefinedExternally() )
                 continue;
 
             wxLogTrace( traceEnvVars, "Saving environment variable config entry %s as %s",
-                        GetChars( it->first ),  GetChars( it->second.GetValue() ) );
-            m_common_settings->Write( it->first, it->second.GetValue() );
-        }
+                        GetChars( m_local_env_var.first ),
+                        GetChars( m_local_env_var.second.GetValue() ) );
 
-        m_common_settings->SetPath( ".." );
+            std::string key( m_local_env_var.first.ToUTF8() );
+            GetCommonSettings()->m_Env.vars[ key ] = m_local_env_var.second.GetValue();
+        }
     }
 }
 
 
+COMMON_SETTINGS* PGM_BASE::GetCommonSettings() const
+{
+    return GetSettingsManager().GetCommonSettings();
+}
+
+
 bool PGM_BASE::SetLanguage( bool first_time )
 {
     bool     retv = true;
@@ -638,10 +557,8 @@ bool PGM_BASE::SetLanguage( bool first_time )
     {
         setLanguageId( wxLANGUAGE_DEFAULT );
         // First time SetLanguage is called, the user selected language id is set
-        // from commun user config settings
-        wxString languageSel;
-
-        m_common_settings->Read( languageCfgKey, &languageSel );
+        // from common user config settings
+        wxString languageSel = GetCommonSettings()->m_System.language;
 
         // Search for the current selection
         for( unsigned ii = 0; LanguagesList[ii].m_KI_Lang_Identifier != 0; ii++ )
@@ -695,7 +612,7 @@ bool PGM_BASE::SetLanguage( bool first_time )
             }
         }
 
-        m_common_settings->Write( languageCfgKey, languageSel );
+        GetCommonSettings()->m_System.language = languageSel;
     }
 
     // Test if floating point notation is working (bug encountered in cross compilation)
@@ -797,17 +714,15 @@ void PGM_BASE::SetLocalEnvVariables( const ENV_VAR_MAP& aEnvVarMap )
     m_local_env_vars.clear();
     m_local_env_vars = aEnvVarMap;
 
-    if( m_common_settings )
-        m_common_settings->DeleteGroup( pathEnvVariables );
-
     SaveCommonSettings();
 
     // Overwrites externally defined environment variable until the next time the application
     // is run.
-    for( ENV_VAR_MAP_ITER it = m_local_env_vars.begin(); it != m_local_env_vars.end(); ++it )
+    for( auto& m_local_env_var : m_local_env_vars )
     {
         wxLogTrace( traceEnvVars, "Setting local environment variable %s to %s.",
-                    GetChars( it->first ), GetChars( it->second.GetValue() ) );
-        wxSetEnv( it->first, it->second.GetValue() );
+                    GetChars( m_local_env_var.first ),
+                    GetChars( m_local_env_var.second.GetValue() ) );
+        wxSetEnv( m_local_env_var.first, m_local_env_var.second.GetValue() );
     }
 }
diff --git a/common/printout.cpp b/common/printout.cpp
index a9dbfcec98..709d1e213a 100644
--- a/common/printout.cpp
+++ b/common/printout.cpp
@@ -16,21 +16,22 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <printout.h>
 #include <pcbplot.h>
-#include <wx/config.h>
+#include <printout.h>
+#include <settings/app_settings.h>
 
-void PRINTOUT_SETTINGS::Save( wxConfigBase* aConfig )
+
+void PRINTOUT_SETTINGS::Save( APP_SETTINGS_BASE* aConfig )
 {
-    aConfig->Write( OPTKEY_PRINT_SCALE, m_scale );
-    aConfig->Write( OPTKEY_PRINT_PAGE_FRAME, m_titleBlock );
-    aConfig->Write( OPTKEY_PRINT_MONOCHROME_MODE, m_blackWhite );
+    aConfig->m_Printing.monochrome  = m_blackWhite;
+    aConfig->m_Printing.title_block = m_titleBlock;
+    aConfig->m_Printing.scale       = m_scale;
 }
 
 
-void PRINTOUT_SETTINGS::Load( wxConfigBase* aConfig )
+void PRINTOUT_SETTINGS::Load( APP_SETTINGS_BASE* aConfig )
 {
-    aConfig->Read( OPTKEY_PRINT_SCALE, &m_scale, 1.0 );
-    aConfig->Read( OPTKEY_PRINT_PAGE_FRAME, &m_titleBlock, false );
-    aConfig->Read( OPTKEY_PRINT_MONOCHROME_MODE, &m_blackWhite, 1 );
+    m_blackWhite = aConfig->m_Printing.monochrome;
+    m_titleBlock = aConfig->m_Printing.title_block;
+    m_scale      = aConfig->m_Printing.scale;
 }
diff --git a/common/settings/app_settings.cpp b/common/settings/app_settings.cpp
new file mode 100644
index 0000000000..c6782b0416
--- /dev/null
+++ b/common/settings/app_settings.cpp
@@ -0,0 +1,254 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 <class_draw_panel_gal.h>
+#include <common.h>
+#include <layers_id_colors_and_visibility.h>
+#include <pgm_base.h>
+#include <settings/app_settings.h>
+#include <settings/common_settings.h>
+#include <settings/parameters.h>
+
+
+///! Update the schema version whenever a migration is required
+const int appSettingsSchemaVersion = 0;
+
+
+APP_SETTINGS_BASE::APP_SETTINGS_BASE( std::string aFilename, int aSchemaVersion ) :
+        JSON_SETTINGS( std::move( aFilename ), SETTINGS_LOC::USER, appSettingsSchemaVersion ),
+        m_Printing(), m_System(), m_Window(), m_appSettingsSchemaVersion( aSchemaVersion )
+{
+    m_params.emplace_back( new PARAM<int>( "find_replace.flags", &m_FindReplace.flags, 1 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "find_replace.find_string",
+            &m_FindReplace.find_string, "" ) );
+
+    m_params.emplace_back( new PARAM_LIST<wxString>( "find_replace.find_history",
+            &m_FindReplace.find_history, {} ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "find_replace.replace_string",
+            &m_FindReplace.replace_string, "" ) );
+
+    m_params.emplace_back( new PARAM_LIST<wxString>( "find_replace.replace_history",
+            &m_FindReplace.replace_history, {} ) );
+
+#ifdef __WXMAC__
+    // Cairo renderer doesn't handle Retina displays so default to OpenGL
+    m_params.emplace_back( new PARAM<int>( "graphics.canvas_type", &m_Graphics.canvas_type,
+            EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL ) );
+#else
+    m_params.emplace_back( new PARAM<int>( "graphics.canvas_type", &m_Graphics.canvas_type,
+            EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ) );
+#endif
+
+    m_params.emplace_back(
+            new PARAM<int>( "lib_tree.column_width", &m_LibTree.column_width, 360 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "printing.monochrome", &m_Printing.monochrome, true ) );
+
+    m_params.emplace_back( new PARAM<double>( "printing.scale", &m_Printing.scale, 1.0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "printing.title_block",
+            &m_Printing.title_block, false ) );
+
+    m_params.emplace_back( new PARAM_LIST<int>( "printing.layers", &m_Printing.layers, {} ) );
+
+    m_params.emplace_back( new PARAM<bool>( "system.first_run_shown",
+            &m_System.first_run_shown, false ) );
+
+    m_params.emplace_back( new PARAM<int>( "system.max_undo_items", &m_System.max_undo_items, 0 ) );
+
+
+    m_params.emplace_back( new PARAM_LIST<wxString>( "system.file_history",
+            &m_System.file_history, {} ) );
+
+    m_params.emplace_back( new PARAM<int>( "system.units",  &m_System.units,
+            static_cast<int>( EDA_UNITS::MILLIMETRES ) ) );
+
+    addParamsForWindow( &m_Window, "window" );
+}
+
+
+bool APP_SETTINGS_BASE::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = true;
+
+    const std::string f = getLegacyFrameName();
+
+    ret &= fromLegacyString(   aCfg, "LastFindString",      "find_replace.find_string" );
+    ret &= fromLegacyString(   aCfg, "LastReplaceString",   "find_replace.replace_string" );
+
+    migrateFindReplace( aCfg );
+
+    ret &= fromLegacy<int>( aCfg, "canvas_type",            "graphics.canvas_type" );
+
+    ret &= fromLegacy<int>( aCfg, "P22LIB_TREE_MODEL_ADAPTERSelectorColumnWidth",
+            "lib_tree.column_width" );
+
+    ret &= fromLegacy<bool>(   aCfg, "PrintMonochrome",         "printing.monochrome" );
+    ret &= fromLegacy<double>( aCfg, "PrintScale",              "printing.scale" );
+    ret &= fromLegacy<bool>(   aCfg, "PrintPageFrame",          "printing.title_block" );
+
+    {
+        nlohmann::json js = nlohmann::json::array();
+        wxString       key;
+        bool           val = false;
+
+        for( unsigned i = 0; i < PCB_LAYER_ID_COUNT; ++i )
+        {
+            key.Printf( wxT( "PlotLayer_%d" ), i );
+
+            if( aCfg->Read( key, &val ) && val )
+                js.push_back( i );
+        }
+
+        ( *this )[PointerFromString( "printing.layers" ) ] = js;
+    }
+
+    ret &= fromLegacy<bool>(   aCfg, f + "FirstRunShown",       "system.first_run_shown" );
+    ret &= fromLegacy<int>(    aCfg, f + "DevelMaxUndoItems",   "system.max_undo_items" );
+    ret &= fromLegacy<int>(    aCfg, f + "Units",               "system.units" );
+
+    {
+        int            max_history_size = Pgm().GetCommonSettings()->m_System.file_history_size;
+        wxString       file, key;
+        nlohmann::json js = nlohmann::json::array();
+
+        for( int i = 1; i <= max_history_size; i++ )
+        {
+            key.Printf( "file%d", i );
+            file = aCfg->Read( key, wxEmptyString );
+
+            if( !file.IsEmpty() )
+                js.push_back( file.ToStdString() );
+        }
+
+        ( *this )[PointerFromString( "system.file_history" )] = js;
+    }
+
+    ret &= migrateWindowConfig( aCfg, f, "window" );
+
+    return ret;
+}
+
+
+void APP_SETTINGS_BASE::migrateFindReplace( wxConfigBase* aCfg )
+{
+    const int find_replace_history_size = 10;
+    nlohmann::json find_history         = nlohmann::json::array();
+    nlohmann::json replace_history      = nlohmann::json::array();
+    wxString tmp, find_key, replace_key;
+
+    for( int i = 0; i < find_replace_history_size; ++i )
+    {
+        find_key.Printf( "FindStringHistoryList%d", i );
+        replace_key.Printf( "ReplaceStringHistoryList%d", i );
+
+        if( aCfg->Read( find_key, &tmp ) )
+            find_history.push_back( tmp.ToStdString() );
+
+        if( aCfg->Read( replace_key, &tmp ) )
+            replace_history.push_back( tmp.ToStdString() );
+    }
+
+    ( *this )[PointerFromString( "find_replace.find_history" )] = find_history;
+    ( *this )[PointerFromString( "find_replace.replace_history" )] = replace_history;
+}
+
+
+bool APP_SETTINGS_BASE::migrateWindowConfig( wxConfigBase* aCfg, const std::string& aFrame,
+                                             const std::string& aJsonPath )
+{
+    bool ret = true;
+
+    const std::string gd = "GalDisplayOptions";
+
+    ret &= fromLegacy<bool>( aCfg, aFrame + "Maximized",            aJsonPath + ".maximized" );
+    ret &= fromLegacyString( aCfg, aFrame + "MostRecentlyUsedPath", aJsonPath + ".mru_path" );
+    ret &= fromLegacy<int>(  aCfg, aFrame + "Size_x",               aJsonPath + ".size_x" );
+    ret &= fromLegacy<int>(  aCfg, aFrame + "Size_y",               aJsonPath + ".size_y" );
+    ret &= fromLegacyString( aCfg, aFrame + "Perspective",          aJsonPath + ".perspective" );
+    ret &= fromLegacy<int>(  aCfg, aFrame + "Pos_x",                aJsonPath + ".pos_x" );
+    ret &= fromLegacy<int>(  aCfg, aFrame + "Pos_y",                aJsonPath + ".pos_y" );
+
+    ret &= fromLegacy<bool>(   aCfg,
+            aFrame + gd + "ForceDisplayCursor", aJsonPath + ".cursor.always_show_cursor" );
+    ret &= fromLegacy<bool>(   aCfg,
+            aFrame + gd + "CursorFullscreen",   aJsonPath + ".cursor.fullscreen_cursor" );
+
+    ret &= fromLegacy<int>(    aCfg,
+            aFrame + "_LastGridSize",        aJsonPath + ".grid.last_size" );
+    ret &= fromLegacy<bool>(   aCfg,
+            aFrame + gd + "GridAxesEnabled", aJsonPath + ".grid.axes_enabled" );
+    ret &= fromLegacy<double>( aCfg,
+            aFrame + gd + "GridLineWidth",   aJsonPath + ".grid.line_width" );
+    ret &= fromLegacy<double>( aCfg,
+            aFrame + gd + "GridMaxDensity",  aJsonPath + ".grid.min_spacing" );
+    ret &= fromLegacy<bool>(   aCfg, aFrame + gd + "ShowGrid",        aJsonPath + ".grid.show" );
+    ret &= fromLegacy<int>(    aCfg, aFrame + gd + "GridStyle",       aJsonPath + ".grid.style" );
+    ret &= fromLegacyColor(    aCfg, aFrame + gd + "GridColor",       aJsonPath + ".grid.color" );
+
+    ret &= fromLegacy<bool>(   aCfg, aFrame + "AutoZoom",            aJsonPath + ".auto_zoom" );
+    ret &= fromLegacy<double>( aCfg, aFrame + "Zoom",                aJsonPath + ".zoom" );
+
+    return ret;
+}
+
+
+void APP_SETTINGS_BASE::addParamsForWindow( WINDOW_SETTINGS* aWindow, const std::string& aJsonPath )
+{
+    m_params.emplace_back(
+            new PARAM<bool>( aJsonPath + ".maximized", &aWindow->maximized, false ) );
+
+    m_params.emplace_back( new PARAM<wxString>( aJsonPath + ".mru_path", &aWindow->mru_path, "" ) );
+
+    m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_x", &aWindow->size_x, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( aJsonPath + ".size_y", &aWindow->size_y, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<wxString>( aJsonPath + ".perspective", &aWindow->perspective, "" ) );
+
+    m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_x", &aWindow->pos_x, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( aJsonPath + ".pos_y", &aWindow->pos_y, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( aJsonPath + ".grid.axes_enabled",
+            &aWindow->grid.axes_enabled, false ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( aJsonPath + ".grid.last_size", &aWindow->grid.last_size, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<double>( aJsonPath + ".grid.line_width", &aWindow->grid.line_width, 1.0 ) );
+
+    m_params.emplace_back(
+            new PARAM<double>( aJsonPath + ".grid.min_spacing", &aWindow->grid.min_spacing, 10 ) );
+
+    m_params.emplace_back( new PARAM<bool>( aJsonPath + ".grid.show", &aWindow->grid.show, true ) );
+
+    m_params.emplace_back( new PARAM<int>( aJsonPath + ".grid.style", &aWindow->grid.style, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( aJsonPath + ".cursor.always_show_cursor",
+            &aWindow->cursor.always_show_cursor, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( aJsonPath + ".cursor.fullscreen_cursor",
+            &aWindow->cursor.fullscreen_cursor, false ) );
+}
diff --git a/common/settings/color_settings.cpp b/common/settings/color_settings.cpp
new file mode 100644
index 0000000000..d7c6bdc4ec
--- /dev/null
+++ b/common/settings/color_settings.cpp
@@ -0,0 +1,345 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 <layers_id_colors_and_visibility.h>
+#include <settings/color_settings.h>
+#include <settings/parameters.h>
+
+
+///! Update the schema version whenever a migration is required
+const int colorsSchemaVersion = 0;
+
+
+COLOR_SETTINGS::COLOR_SETTINGS( std::string aFilename ) :
+        JSON_SETTINGS( std::move( aFilename ), SETTINGS_LOC::COLORS, colorsSchemaVersion ),
+        m_Palette(), m_colors(), m_color_context( COLOR_CONTEXT::PCB )
+{
+
+    m_params.emplace_back( new PARAM<wxString>( "meta.name", &m_displayName, "KiCad Default" ) );
+
+    std::vector<COLOR4D> default_palette = {
+            COLOR4D( RED ),
+            COLOR4D( YELLOW ),
+            COLOR4D( LIGHTMAGENTA ),
+            COLOR4D( LIGHTRED ),
+            COLOR4D( CYAN ),
+            COLOR4D( GREEN ),
+            COLOR4D( BLUE ),
+            COLOR4D( DARKGRAY ),
+            COLOR4D( MAGENTA ),
+            COLOR4D( LIGHTGRAY ),
+            COLOR4D( MAGENTA ),
+            COLOR4D( RED ),
+            COLOR4D( BROWN ),
+            COLOR4D( LIGHTGRAY ),
+            COLOR4D( BLUE ),
+            COLOR4D( GREEN )
+            };
+
+    // TODO(JE) in actual usage, how long does the default palette need to be?
+    m_params.emplace_back( new PARAM_LIST<COLOR4D>( "palette", &m_Palette, default_palette ) );
+
+#define CLR( x, y, z ) m_params.emplace_back( new COLOR_MAP_PARAM( x, y, z, &m_colors ) );
+
+    CLR( "schematic.background",        LAYER_SCHEMATIC_BACKGROUND, COLOR4D( WHITE ) );
+    CLR( "schematic.brightened",        LAYER_BRIGHTENED,           COLOR4D( PUREMAGENTA ) );
+    CLR( "schematic.bus",               LAYER_BUS,                  COLOR4D( BLUE ) );
+    CLR( "schematic.component_body",    LAYER_DEVICE_BACKGROUND,    COLOR4D( LIGHTYELLOW ) );
+    CLR( "schematic.component_outline", LAYER_DEVICE,               COLOR4D( RED ) );
+    CLR( "schematic.cursor",            LAYER_SCHEMATIC_CURSOR,     COLOR4D( BLACK ) );
+    CLR( "schematic.erc_error",         LAYER_ERC_ERR,        COLOR4D( RED ).WithAlpha( 0.8 ) );
+    CLR( "schematic.erc_warning",       LAYER_ERC_WARN,       COLOR4D( GREEN ).WithAlpha( 0.8 ) );
+    CLR( "schematic.fields",            LAYER_FIELDS,               COLOR4D( MAGENTA ) );
+    CLR( "schematic.grid",              LAYER_SCHEMATIC_GRID,       COLOR4D( DARKGRAY ) );
+    CLR( "schematic.hidden",            LAYER_HIDDEN,               COLOR4D( LIGHTGRAY ) );
+    CLR( "schematic.junction",          LAYER_JUNCTION,             COLOR4D( GREEN ) );
+    CLR( "schematic.label_global",      LAYER_GLOBLABEL,            COLOR4D( RED ) );
+    CLR( "schematic.label_hier",        LAYER_HIERLABEL,            COLOR4D( BROWN ) );
+    CLR( "schematic.label_local",       LAYER_LOCLABEL,             COLOR4D( BLACK ) );
+    CLR( "schematic.net_name",          LAYER_NETNAM,               COLOR4D( DARKGRAY ) );
+    CLR( "schematic.no_connect",        LAYER_NOCONNECT,            COLOR4D( BLUE ) );
+    CLR( "schematic.note",              LAYER_NOTES,                COLOR4D( LIGHTBLUE ) );
+    CLR( "schematic.pin",               LAYER_PIN,                  COLOR4D( RED ) );
+    CLR( "schematic.pin_name",          LAYER_PINNAM,               COLOR4D( CYAN ) );
+    CLR( "schematic.pin_number",        LAYER_PINNUM,               COLOR4D( RED ) );
+    CLR( "schematic.reference",         LAYER_REFERENCEPART,        COLOR4D( CYAN ) );
+    // Macs look better with a lighter shadow
+#ifdef __WXMAC__
+    CLR( "schematic.shadow",            LAYER_SELECTION_SHADOWS,    COLOR4D( .78, .92, 1.0, 0.8 ) );
+#else
+    CLR( "schematic.shadow",            LAYER_SELECTION_SHADOWS,    COLOR4D( .4, .7, 1.0, 0.8 ) );
+#endif
+    CLR( "schematic.sheet",             LAYER_SHEET,                COLOR4D( MAGENTA ) );
+    CLR( "schematic.sheet_filename",    LAYER_SHEETFILENAME,        COLOR4D( BROWN ) );
+    CLR( "schematic.sheet_label",       LAYER_SHEETLABEL,           COLOR4D( CYAN ) );
+    CLR( "schematic.sheet_name",        LAYER_SHEETNAME,            COLOR4D( CYAN ) );
+    CLR( "schematic.value",             LAYER_VALUEPART,            COLOR4D( CYAN ) );
+    CLR( "schematic.wire",              LAYER_WIRE,                 COLOR4D( GREEN ) );
+    CLR( "schematic.worksheet",         LAYER_SCHEMATIC_WORKSHEET,  COLOR4D( BLACK ) );
+
+    CLR( "gerbview.axes",               LAYER_GERBVIEW_AXES,        COLOR4D( BLUE ) );
+    CLR( "gerbview.background",         LAYER_GERBVIEW_BACKGROUND,  COLOR4D( BLACK ) );
+    CLR( "gerbview.dcodes",             LAYER_DCODES,               COLOR4D( WHITE ) );
+    CLR( "gerbview.grid",               LAYER_GERBVIEW_GRID,        COLOR4D( MAGENTA ) );
+    CLR( "gerbview.negative_objects",   LAYER_NEGATIVE_OBJECTS,     COLOR4D( DARKGRAY ) );
+    CLR( "gerbview.worksheet",          LAYER_GERBVIEW_WORKSHEET,   COLOR4D( BLUE ) );
+
+    // TODO(JE) New default scheme for GerbView
+    for( int i = 0, id = GERBVIEW_LAYER_ID_START;
+         id < GERBER_DRAWLAYERS_COUNT + GERBVIEW_LAYER_ID_START; ++i, ++id )
+    {
+        CLR( "gerbview.layers." + std::to_string( i ), id,
+                default_palette[ i % default_palette.size() ] );
+    }
+
+    CLR( "board.anchor",                   LAYER_ANCHOR,             COLOR4D( BLUE ) );
+    CLR( "board.aux_items",                LAYER_AUX_ITEMS,          COLOR4D( WHITE ) );
+    CLR( "board.background",               LAYER_PCB_BACKGROUND,     COLOR4D( BLACK ) );
+    CLR( "board.cursor",                   LAYER_CURSOR,             COLOR4D( WHITE ) );
+    CLR( "board.drc",                      LAYER_DRC,                COLOR4D( LIGHTGRAY ) );
+    CLR( "board.footprint_text_back",      LAYER_MOD_TEXT_BK,        COLOR4D( BLUE ) );
+    CLR( "board.footprint_text_front",     LAYER_MOD_TEXT_FR,        COLOR4D( LIGHTGRAY ) );
+    CLR( "board.footprint_text_invisible", LAYER_MOD_TEXT_INVISIBLE, COLOR4D( LIGHTGRAY ) );
+    CLR( "board.grid",                     LAYER_GRID,               COLOR4D( DARKGRAY ) );
+    CLR( "board.grid_axes",                LAYER_GRID_AXES,          COLOR4D( LIGHTGRAY ) );
+    CLR( "board.microvia",                 LAYER_VIA_MICROVIA,       COLOR4D( LIGHTGRAY ) );
+    CLR( "board.no_connect",               LAYER_NO_CONNECTS,        COLOR4D( BLUE ) );
+    CLR( "board.pad_back",                 LAYER_PAD_BK,             COLOR4D( GREEN ) );
+    CLR( "board.pad_front",                LAYER_PAD_FR,             COLOR4D( RED ) );
+    CLR( "board.pad_plated_hole",          LAYER_PADS_PLATEDHOLES,   COLOR4D( YELLOW ) );
+    CLR( "board.pad_through_hole",         LAYER_PADS_TH,            COLOR4D( YELLOW ) );
+    CLR( "board.plated_hole",              LAYER_NON_PLATEDHOLES,    COLOR4D( YELLOW ) );
+    CLR( "board.ratsnest",                 LAYER_RATSNEST,           COLOR4D( WHITE ) );
+    CLR( "board.select_overlay",           LAYER_SELECT_OVERLAY,     COLOR4D( DARKRED ) );
+    CLR( "board.through_via",              LAYER_VIA_THROUGH,        COLOR4D( LIGHTGRAY ) );
+    CLR( "board.via",                      LAYER_VIAS,               COLOR4D( BLACK ) );
+    CLR( "board.via_blind_buried",         LAYER_VIA_BBLIND,         COLOR4D( BROWN ) );
+    CLR( "board.via_hole",                 LAYER_VIAS_HOLES,         COLOR4D( WHITE ) );
+    CLR( "board.via_micro",                LAYER_VIA_MICROVIA,       COLOR4D( CYAN ) );
+    CLR( "board.via_through",              LAYER_VIA_THROUGH,        COLOR4D( LIGHTGRAY ) );
+    CLR( "board.worksheet",                LAYER_WORKSHEET,          COLOR4D( DARKRED ) );
+
+    CLR( "board.copper.f",      F_Cu,       COLOR4D( RED ) );
+    CLR( "board.copper.in1",    In1_Cu,     COLOR4D( YELLOW ) );
+    CLR( "board.copper.in2",    In2_Cu,     COLOR4D( LIGHTMAGENTA ) );
+    CLR( "board.copper.in3",    In3_Cu,     COLOR4D( LIGHTRED ) );
+    CLR( "board.copper.in4",    In4_Cu,     COLOR4D( CYAN ) );
+    CLR( "board.copper.in5",    In5_Cu,     COLOR4D( GREEN ) );
+    CLR( "board.copper.in6",    In6_Cu,     COLOR4D( BLUE ) );
+    CLR( "board.copper.in7",    In7_Cu,     COLOR4D( DARKGRAY ) );
+    CLR( "board.copper.in8",    In8_Cu,     COLOR4D( MAGENTA ) );
+    CLR( "board.copper.in9",    In9_Cu,     COLOR4D( LIGHTGRAY ) );
+    CLR( "board.copper.in10",   In10_Cu,    COLOR4D( MAGENTA ) );
+    CLR( "board.copper.in11",   In11_Cu,    COLOR4D( RED ) );
+    CLR( "board.copper.in12",   In12_Cu,    COLOR4D( BROWN ) );
+    CLR( "board.copper.in13",   In13_Cu,    COLOR4D( LIGHTGRAY ) );
+    CLR( "board.copper.in14",   In14_Cu,    COLOR4D( BLUE ) );
+    CLR( "board.copper.in15",   In15_Cu,    COLOR4D( GREEN ) );
+    CLR( "board.copper.in16",   In16_Cu,    COLOR4D( RED ) );
+    CLR( "board.copper.in17",   In17_Cu,    COLOR4D( YELLOW ) );
+    CLR( "board.copper.in18",   In18_Cu,    COLOR4D( LIGHTMAGENTA ) );
+    CLR( "board.copper.in19",   In19_Cu,    COLOR4D( LIGHTRED ) );
+    CLR( "board.copper.in20",   In20_Cu,    COLOR4D( CYAN ) );
+    CLR( "board.copper.in21",   In21_Cu,    COLOR4D( GREEN ) );
+    CLR( "board.copper.in22",   In22_Cu,    COLOR4D( BLUE ) );
+    CLR( "board.copper.in23",   In23_Cu,    COLOR4D( DARKGRAY ) );
+    CLR( "board.copper.in24",   In24_Cu,    COLOR4D( MAGENTA ) );
+    CLR( "board.copper.in25",   In25_Cu,    COLOR4D( LIGHTGRAY ) );
+    CLR( "board.copper.in26",   In26_Cu,    COLOR4D( MAGENTA ) );
+    CLR( "board.copper.in27",   In27_Cu,    COLOR4D( RED ) );
+    CLR( "board.copper.in28",   In28_Cu,    COLOR4D( BROWN ) );
+    CLR( "board.copper.in29",   In29_Cu,    COLOR4D( LIGHTGRAY ) );
+    CLR( "board.copper.in30",   In30_Cu,    COLOR4D( BLUE ) );
+    CLR( "board.copper.b",      B_Cu,       COLOR4D( GREEN ) );
+
+    CLR( "board.b_adhes",       B_Adhes,    COLOR4D( BLUE ) );
+    CLR( "board.f_adhes",       F_Adhes,    COLOR4D( MAGENTA ) );
+    CLR( "board.b_paste",       B_Paste,    COLOR4D( LIGHTCYAN ) );
+    CLR( "board.f_paste",       F_Paste,    COLOR4D( RED ) );
+    CLR( "board.b_silks",       B_SilkS,    COLOR4D( MAGENTA ) );
+    CLR( "board.f_silks",       F_SilkS,    COLOR4D( CYAN ) );
+    CLR( "board.b_mask",        B_Mask,     COLOR4D( BROWN ) );
+    CLR( "board.f_mask",        F_Mask,     COLOR4D( MAGENTA ) );
+    CLR( "board.dwgs_user",     Dwgs_User,  COLOR4D( LIGHTGRAY ) );
+    CLR( "board.cmts_user",     Cmts_User,  COLOR4D( BLUE ) );
+    CLR( "board.eco1_user",     Eco1_User,  COLOR4D( GREEN ) );
+    CLR( "board.eco2_user",     Eco2_User,  COLOR4D( YELLOW ) );
+    CLR( "board.edge_cuts",     Edge_Cuts,  COLOR4D( YELLOW ) );
+    CLR( "board.margin",        Margin,     COLOR4D( LIGHTMAGENTA ) );
+    CLR( "board.b_crtyd",       B_CrtYd,    COLOR4D( DARKGRAY ) );
+    CLR( "board.f_crtyd",       F_CrtYd,    COLOR4D( LIGHTGRAY ) );
+    CLR( "board.b_fab",         B_Fab,      COLOR4D( BLUE ) );
+    CLR( "board.f_fab",         F_Fab,      COLOR4D( DARKGRAY ) );
+
+    // TODO(JE) Storing fpedit colors here is a temporary hack to preserve user settings.
+    // Ultimately, if a user wants to have different colors for pcbnew and the footprint editor,
+    // they should simply choose a different named color theme for each.
+    // While we only have a single color theme, we need to store two mappings of all the
+    // pcb-related colors, one for pcbnew and one for footprint editor.
+    // Once color themes are supported, we should bump the schema version of COLOR_SETTINGS
+    // and in the migration split out the "User" theme to "User.FpEdit" or something, then set
+    // the User.FpEdit scheme as active for the footprint editor.
+
+#define FL FPEDIT_LAYER_ID_START
+
+    CLR( "fpedit.anchor",                   FL + LAYER_ANCHOR,             COLOR4D( BLUE ) );
+    CLR( "fpedit.aux_items",                FL + LAYER_AUX_ITEMS,          COLOR4D( WHITE ) );
+    CLR( "fpedit.background",               FL + LAYER_PCB_BACKGROUND,     COLOR4D( BLACK ) );
+    CLR( "fpedit.cursor",                   FL + LAYER_CURSOR,             COLOR4D( WHITE ) );
+    CLR( "fpedit.drc",                      FL + LAYER_DRC,                COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.footprint_text_back",      FL + LAYER_MOD_TEXT_BK,        COLOR4D( BLUE ) );
+    CLR( "fpedit.footprint_text_front",     FL + LAYER_MOD_TEXT_FR,        COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.footprint_text_invisible", FL + LAYER_MOD_TEXT_INVISIBLE, COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.grid",                     FL + LAYER_GRID,               COLOR4D( DARKGRAY ) );
+    CLR( "fpedit.grid_axes",                FL + LAYER_GRID_AXES,          COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.microvia",                 FL + LAYER_VIA_MICROVIA,       COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.no_connect",               FL + LAYER_NO_CONNECTS,        COLOR4D( BLUE ) );
+    CLR( "fpedit.pad_back",                 FL + LAYER_PAD_BK,             COLOR4D( GREEN ) );
+    CLR( "fpedit.pad_front",                FL + LAYER_PAD_FR,             COLOR4D( RED ) );
+    CLR( "fpedit.pad_plated_hole",          FL + LAYER_PADS_PLATEDHOLES,   COLOR4D( YELLOW ) );
+    CLR( "fpedit.pad_through_hole",         FL + LAYER_PADS_TH,            COLOR4D( YELLOW ) );
+    CLR( "fpedit.plated_hole",              FL + LAYER_NON_PLATEDHOLES,    COLOR4D( YELLOW ) );
+    CLR( "fpedit.ratsnest",                 FL + LAYER_RATSNEST,           COLOR4D( WHITE ) );
+    CLR( "fpedit.select_overlay",           FL + LAYER_SELECT_OVERLAY,     COLOR4D( DARKRED ) );
+    CLR( "fpedit.through_via",              FL + LAYER_VIA_THROUGH,        COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.via",                      FL + LAYER_VIAS,               COLOR4D( BLACK ) );
+    CLR( "fpedit.via_blind_buried",         FL + LAYER_VIA_BBLIND,         COLOR4D( BROWN ) );
+    CLR( "fpedit.via_hole",                 FL + LAYER_VIAS_HOLES,         COLOR4D( WHITE ) );
+    CLR( "fpedit.via_micro",                FL + LAYER_VIA_MICROVIA,       COLOR4D( CYAN ) );
+    CLR( "fpedit.via_through",              FL + LAYER_VIA_THROUGH,        COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.worksheet",                FL + LAYER_WORKSHEET,          COLOR4D( DARKRED ) );
+
+    CLR( "fpedit.copper.f",      FL + F_Cu,       COLOR4D( RED ) );
+    CLR( "fpedit.copper.in1",    FL + In1_Cu,     COLOR4D( YELLOW ) );
+    CLR( "fpedit.copper.in2",    FL + In2_Cu,     COLOR4D( LIGHTMAGENTA ) );
+    CLR( "fpedit.copper.in3",    FL + In3_Cu,     COLOR4D( LIGHTRED ) );
+    CLR( "fpedit.copper.in4",    FL + In4_Cu,     COLOR4D( CYAN ) );
+    CLR( "fpedit.copper.in5",    FL + In5_Cu,     COLOR4D( GREEN ) );
+    CLR( "fpedit.copper.in6",    FL + In6_Cu,     COLOR4D( BLUE ) );
+    CLR( "fpedit.copper.in7",    FL + In7_Cu,     COLOR4D( DARKGRAY ) );
+    CLR( "fpedit.copper.in8",    FL + In8_Cu,     COLOR4D( MAGENTA ) );
+    CLR( "fpedit.copper.in9",    FL + In9_Cu,     COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.copper.in10",   FL + In10_Cu,    COLOR4D( MAGENTA ) );
+    CLR( "fpedit.copper.in11",   FL + In11_Cu,    COLOR4D( RED ) );
+    CLR( "fpedit.copper.in12",   FL + In12_Cu,    COLOR4D( BROWN ) );
+    CLR( "fpedit.copper.in13",   FL + In13_Cu,    COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.copper.in14",   FL + In14_Cu,    COLOR4D( BLUE ) );
+    CLR( "fpedit.copper.in15",   FL + In15_Cu,    COLOR4D( GREEN ) );
+    CLR( "fpedit.copper.in16",   FL + In16_Cu,    COLOR4D( RED ) );
+    CLR( "fpedit.copper.in17",   FL + In17_Cu,    COLOR4D( YELLOW ) );
+    CLR( "fpedit.copper.in18",   FL + In18_Cu,    COLOR4D( LIGHTMAGENTA ) );
+    CLR( "fpedit.copper.in19",   FL + In19_Cu,    COLOR4D( LIGHTRED ) );
+    CLR( "fpedit.copper.in20",   FL + In20_Cu,    COLOR4D( CYAN ) );
+    CLR( "fpedit.copper.in21",   FL + In21_Cu,    COLOR4D( GREEN ) );
+    CLR( "fpedit.copper.in22",   FL + In22_Cu,    COLOR4D( BLUE ) );
+    CLR( "fpedit.copper.in23",   FL + In23_Cu,    COLOR4D( DARKGRAY ) );
+    CLR( "fpedit.copper.in24",   FL + In24_Cu,    COLOR4D( MAGENTA ) );
+    CLR( "fpedit.copper.in25",   FL + In25_Cu,    COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.copper.in26",   FL + In26_Cu,    COLOR4D( MAGENTA ) );
+    CLR( "fpedit.copper.in27",   FL + In27_Cu,    COLOR4D( RED ) );
+    CLR( "fpedit.copper.in28",   FL + In28_Cu,    COLOR4D( BROWN ) );
+    CLR( "fpedit.copper.in29",   FL + In29_Cu,    COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.copper.in30",   FL + In30_Cu,    COLOR4D( BLUE ) );
+    CLR( "fpedit.copper.b",      FL + B_Cu,       COLOR4D( GREEN ) );
+
+    CLR( "fpedit.b_adhes",       FL + B_Adhes,    COLOR4D( BLUE ) );
+    CLR( "fpedit.f_adhes",       FL + F_Adhes,    COLOR4D( MAGENTA ) );
+    CLR( "fpedit.b_paste",       FL + B_Paste,    COLOR4D( LIGHTCYAN ) );
+    CLR( "fpedit.f_paste",       FL + F_Paste,    COLOR4D( RED ) );
+    CLR( "fpedit.b_silks",       FL + B_SilkS,    COLOR4D( MAGENTA ) );
+    CLR( "fpedit.f_silks",       FL + F_SilkS,    COLOR4D( CYAN ) );
+    CLR( "fpedit.b_mask",        FL + B_Mask,     COLOR4D( BROWN ) );
+    CLR( "fpedit.f_mask",        FL + F_Mask,     COLOR4D( MAGENTA ) );
+    CLR( "fpedit.dwgs_user",     FL + Dwgs_User,  COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.cmts_user",     FL + Cmts_User,  COLOR4D( BLUE ) );
+    CLR( "fpedit.eco1_user",     FL + Eco1_User,  COLOR4D( GREEN ) );
+    CLR( "fpedit.eco2_user",     FL + Eco2_User,  COLOR4D( YELLOW ) );
+    CLR( "fpedit.edge_cuts",     FL + Edge_Cuts,  COLOR4D( YELLOW ) );
+    CLR( "fpedit.margin",        FL + Margin,     COLOR4D( LIGHTMAGENTA ) );
+    CLR( "fpedit.b_crtyd",       FL + B_CrtYd,    COLOR4D( DARKGRAY ) );
+    CLR( "fpedit.f_crtyd",       FL + F_CrtYd,    COLOR4D( LIGHTGRAY ) );
+    CLR( "fpedit.b_fab",         FL + B_Fab,      COLOR4D( BLUE ) );
+    CLR( "fpedit.f_fab",         FL + F_Fab,      COLOR4D( DARKGRAY ) );
+
+    // Colors for 3D viewer, which are used as defaults unless overridden by the board
+    CLR( "3d_viewer.background_bottom", LAYER_3D_BACKGROUND_BOTTOM, COLOR4D( 0.4, 0.4, 0.5, 1.0 ) );
+    CLR( "3d_viewer.background_top",    LAYER_3D_BACKGROUND_TOP,    COLOR4D( 0.8, 0.8, 0.9, 1.0 ) );
+    CLR( "3d_viewer.board",             LAYER_3D_BOARD,            COLOR4D( 0.2, 0.17, 0.09, 1.0 ) );
+    CLR( "3d_viewer.copper",            LAYER_3D_COPPER,            COLOR4D( 0.7, 0.61, 0.0, 1.0 ) );
+    CLR( "3d_viewer.silkscreen_bottom", LAYER_3D_SILKSCREEN_BOTTOM, COLOR4D( 0.9, 0.9, 0.9, 1.0 ) );
+    CLR( "3d_viewer.silkscreen_top",    LAYER_3D_SILKSCREEN_TOP,    COLOR4D( 0.9, 0.9, 0.9, 1.0 ) );
+    CLR( "3d_viewer.soldermask",        LAYER_3D_SOLDERMASK,       COLOR4D( 0.08, 0.2, 0.14, 1.0 ) );
+    CLR( "3d_viewer.solderpaste",       LAYER_3D_SOLDERPASTE,       COLOR4D( 0.5, 0.5, 0.5, 1.0 ) );
+}
+
+
+bool COLOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    return false;
+}
+
+
+COLOR4D COLOR_SETTINGS::GetColor( int aLayer ) const
+{
+    try
+    {
+        if( m_color_context == COLOR_CONTEXT::FOOTPRINT && aLayer >= PCBNEW_LAYER_ID_START
+                && aLayer <= GAL_LAYER_ID_END )
+            aLayer += FPEDIT_LAYER_ID_START;
+
+        return m_colors.at( aLayer );
+    }
+    catch( std::out_of_range& )
+    {
+        return COLOR4D::UNSPECIFIED;
+    }
+}
+
+
+COLOR4D COLOR_SETTINGS::GetDefaultColor( int aLayer )
+{
+    if( !m_defaultColors.count( aLayer ) )
+    {
+        if( m_color_context == COLOR_CONTEXT::FOOTPRINT && aLayer >= PCBNEW_LAYER_ID_START
+                && aLayer <= GAL_LAYER_ID_END )
+            aLayer += FPEDIT_LAYER_ID_START;
+
+        COLOR_MAP_PARAM* p = nullptr;
+
+        for( auto param : m_params )
+            if( auto cmp = dynamic_cast<COLOR_MAP_PARAM*>( param ) )
+                if( cmp->GetKey() == aLayer )
+                    p = cmp;
+
+        wxASSERT( p );
+        m_defaultColors[aLayer] = p->GetDefault();
+    }
+
+    return m_defaultColors.at( aLayer );;
+}
+
+
+void COLOR_SETTINGS::SetColor( int aLayer, COLOR4D aColor )
+{
+    if( m_color_context == COLOR_CONTEXT::FOOTPRINT )
+        aLayer += FPEDIT_LAYER_ID_START;
+
+    m_colors[ aLayer ] = aColor;
+}
diff --git a/common/settings/common_settings.cpp b/common/settings/common_settings.cpp
new file mode 100644
index 0000000000..1d393fb125
--- /dev/null
+++ b/common/settings/common_settings.cpp
@@ -0,0 +1,169 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 <settings/common_settings.h>
+#include <settings/parameters.h>
+#include <wx/config.h>
+#include <wx/log.h>
+
+
+extern const char* traceSettings;
+
+
+///! Update the schema version whenever a migration is required
+const int commonSchemaVersion = 0;
+
+COMMON_SETTINGS::COMMON_SETTINGS() :
+        JSON_SETTINGS( "kicad_common", SETTINGS_LOC::USER, commonSchemaVersion ),
+        m_Appearance(), m_Env(), m_Input(), m_Graphics(), m_System()
+{
+    // This only effect the first time KiCad is run.  The user's setting will be used for all
+    // subsequent runs.  Menu icons are off by default on OSX and on for all other platforms.
+#if defined( __WXMAC__ )
+    bool defaultUseIconsInMenus = false;
+#else
+    bool defaultUseIconsInMenus = true;
+#endif
+
+    m_params.emplace_back( new PARAM<double>( "appearance.canvas_scale",
+            &m_Appearance.canvas_scale, 1.0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "appearance.icon_scale",
+            &m_Appearance.icon_scale, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "appearance.use_icons_in_menus",
+            &m_Appearance.use_icons_in_menus, defaultUseIconsInMenus ) );
+
+    m_params.emplace_back( new PARAM<bool>( "environment.show_warning_dialog",
+                                         &m_Env.show_warning_dialog, false ) );
+
+    m_params.emplace_back( new PARAM_MAP<wxString>( "environment.vars", &m_Env.vars, {} ) );
+
+    m_params.emplace_back( new PARAM<bool>( "input.auto_pan", &m_Input.auto_pan, false ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "input.center_on_zoom", &m_Input.center_on_zoom, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "input.immediate_actions",
+            &m_Input.immediate_actions, true ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "input.mousewheel_pan", &m_Input.mousewheel_pan, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "input.prefer_select_to_drag",
+            &m_Input.prefer_select_to_drag, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "input.warp_mouse_on_move",
+            &m_Input.warp_mouse_on_move, true ) );
+
+    m_params.emplace_back( new PARAM<int>( "graphics.opengl_antialiasing_mode",
+                                       &m_Graphics.opengl_aa_mode, 0, 0, 4 ) );
+
+    m_params.emplace_back( new PARAM<int>( "graphics.cairo_antialiasing_mode",
+                                       &m_Graphics.cairo_aa_mode, 0, 0, 3 ) );
+
+    m_params.emplace_back( new PARAM<int>( "system.autosave_interval",
+            &m_System.autosave_interval, 600 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "system.editor_name",
+            &m_System.editor_name, "" ) );
+
+    m_params.emplace_back( new PARAM<int>( "system.file_history_size",
+            &m_System.file_history_size, 9 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "system.language",
+            &m_System.language, "Default" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "system.pdf_viewer_name",
+            &m_System.pdf_viewer_name, "" ) );
+
+    m_params.emplace_back( new PARAM<bool>( "system.use_system_pdf_viewer",
+            &m_System.use_system_pdf_viewer, true ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "system.working_dir",
+            &m_System.working_dir, "" ) );
+}
+
+
+bool COMMON_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = true;
+
+    ret &= fromLegacy<double>( aCfg, "CanvasScale",     "appearance.canvas_scale" );
+    ret &= fromLegacy<int>( aCfg,    "IconScale",       "appearance.icon_scale" );
+    ret &= fromLegacy<bool>( aCfg,   "UseIconsInMenus", "appearance.use_icons_in_menus" );
+
+    ret &= fromLegacy<bool>( aCfg, "ShowEnvVarWarningDialog", "environment.show_warning_dialog" );
+
+    auto load_env_vars = [&] () {
+          wxString key, value;
+          long index = 0;
+          nlohmann::json::json_pointer ptr = PointerFromString( "environment.vars" );
+
+          aCfg->SetPath( "EnvironmentVariables" );
+          ( *this )[ptr] = nlohmann::json( {} );
+
+          while( aCfg->GetNextEntry( key, index ) )
+          {
+              value = aCfg->Read( key, wxEmptyString );
+
+              if( !value.IsEmpty() )
+              {
+                  ptr.push_back( key.ToStdString() );
+
+                  wxLogTrace( traceSettings, "Migrate Env: %s=%s", ptr.to_string(), value );
+                  ( *this )[ptr] = value.ToUTF8();
+
+                  ptr.pop_back();
+              }
+          }
+
+          aCfg->SetPath( ".." );
+    };
+
+    load_env_vars();
+
+    ret &= fromLegacy<bool>( aCfg, "AutoPAN",                   "input.auto_pan" );
+    ret &= fromLegacy<bool>( aCfg, "ImmediateActions",          "input.immediate_actions" );
+    ret &= fromLegacy<bool>( aCfg, "MousewheelPAN",             "input.mousewheel_pan" );
+    ret &= fromLegacy<bool>( aCfg, "PreferSelectionToDragging", "input.prefer_select_to_drag" );
+    ret &= fromLegacy<bool>( aCfg, "MoveWarpsCursor",           "input.warp_mouse_on_move" );
+    ret &= fromLegacy<bool>( aCfg, "ZoomNoCenter",              "input.center_on_zoom" );
+
+    // This was stored inverted in legacy config
+    if( ret )
+    {
+        auto p = PointerFromString( "input.center_on_zoom" );
+        ( *this )[p] = !( *this )[p];
+    }
+
+    ret &= fromLegacy<int>( aCfg, "OpenGLAntialiasingMode", "graphics.opengl_antialiasing_mode" );
+    ret &= fromLegacy<int>( aCfg, "CairoAntialiasingMode",  "graphics.cairo_antialiasing_mode" );
+
+    ret &= fromLegacy<int>(  aCfg, "AutoSaveInterval",        "system.autosave_interval" );
+    ret &= fromLegacyString( aCfg, "Editor",                  "system.editor_name" );
+    ret &= fromLegacy<int>(  aCfg, "FileHistorySize",         "system.file_history_size" );
+    ret &= fromLegacyString( aCfg, "LanguageID",              "system.language" );
+    ret &= fromLegacyString( aCfg, "PdfBrowserName",          "system.pdf_viewer_name" );
+    ret &= fromLegacy<bool>( aCfg, "UseSystemBrowser",        "system.use_system_pdf_viewer" );
+    ret &= fromLegacyString( aCfg, "WorkingDir",              "system.working_dir" );
+
+    return ret;
+}
\ No newline at end of file
diff --git a/common/settings/json_settings.cpp b/common/settings/json_settings.cpp
new file mode 100644
index 0000000000..95335fa71c
--- /dev/null
+++ b/common/settings/json_settings.cpp
@@ -0,0 +1,412 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <fstream>
+#include <iomanip>
+#include <utility>
+
+#include <common.h>
+#include <gal/color4d.h>
+#include <settings/json_settings.h>
+#include <settings/nested_settings.h>
+#include <settings/parameters.h>
+#include <wx/config.h>
+#include <wx/debug.h>
+#include <wx/filename.h>
+
+extern const char* traceSettings;
+
+
+JSON_SETTINGS::JSON_SETTINGS( const std::string& aFilename, SETTINGS_LOC aLocation,
+                              int aSchemaVersion, bool aCreateIfMissing, bool aWriteFile,
+                              nlohmann::json aDefault ) :
+        nlohmann::json( std::move( aDefault ) ), m_filename( aFilename ), m_legacy_filename( "" ),
+        m_location( aLocation ), m_createIfMissing( aCreateIfMissing ), m_writeFile( aWriteFile ),
+        m_schemaVersion( aSchemaVersion )
+{
+    m_params.emplace_back(
+            new PARAM<std::string>( "meta.filename", &m_filename, m_filename, true ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "meta.version", &m_schemaVersion, m_schemaVersion, true ) );
+}
+
+
+JSON_SETTINGS::~JSON_SETTINGS()
+{
+    for( auto param: m_params )
+        delete param;
+
+    m_params.clear();
+}
+
+
+void JSON_SETTINGS::Load()
+{
+    for( auto param : m_params )
+        param->Load( this );
+}
+
+
+void JSON_SETTINGS::LoadFromFile( const std::string& aDirectory )
+{
+    // First, load all params to default values
+    clear();
+    Load();
+
+    bool migrated = false;
+    LOCALE_IO locale;
+
+    auto migrateFromLegacy = [&] ( wxFileName& aPath ) {
+        wxConfigBase::DontCreateOnDemand();
+        auto cfg = std::make_unique<wxFileConfig>( wxT( "" ), wxT( "" ), aPath.GetFullPath() );
+
+        // If migrate fails or is not implemented, fall back to built-in defaults that were
+        // already loaded above
+        if( !MigrateFromLegacy( cfg.get() ) )
+        {
+            wxLogTrace( traceSettings,
+                        "%s: migrated; not all settings were found in legacy file", m_filename );
+        }
+        else
+        {
+            wxLogTrace( traceSettings, "%s: migrated from legacy format", m_filename );
+        }
+
+        // Either way, we want to clean up the old file afterwards
+        migrated = true;
+    };
+
+    wxFileName path( aDirectory, m_filename, "json" );
+
+    if( !path.Exists() )
+    {
+        // Case 1: legacy migration, no .json extension yet
+        path.ClearExt();
+
+        if( path.Exists() )
+        {
+            migrateFromLegacy( path );
+        }
+        // Case 2: legacy filename is different from new one
+        else if( !m_legacy_filename.empty() )
+        {
+            path.SetName( m_legacy_filename );
+
+            if( path.Exists() )
+                migrateFromLegacy( path );
+        }
+    }
+    else
+    {
+        try
+        {
+            std::ifstream in( path.GetFullPath().ToStdString() );
+            in >> *this;
+
+            // If parse succeeds, check if schema migration is required
+            try
+            {
+                int filever = at( PointerFromString( "meta.version" ) ).get<int>();
+
+                if( filever < m_schemaVersion )
+                {
+                    wxLogTrace( traceSettings, "%s: attempting migration from version %d to %d",
+                            m_filename, filever, m_schemaVersion );
+
+                    if( !Migrate() )
+                    {
+                        wxLogTrace( traceSettings, "%s: migration failed!", m_filename );
+                    }
+                }
+                else if( filever > m_schemaVersion )
+                {
+                    wxLogTrace( traceSettings,
+                            "%s: warning: file version %d is newer than latest (%d)", m_filename,
+                            filever, m_schemaVersion );
+                }
+            }
+            catch( ... )
+            {
+                wxLogTrace( traceSettings, "%s: file version could not be read!", m_filename );
+            }
+        }
+        catch( nlohmann::json::parse_error& error )
+        {
+            wxLogTrace(
+                    traceSettings, "Parse error reading %s: %s", path.GetFullPath(), error.what() );
+            wxLogTrace( traceSettings, "Attempting migration in case file is in legacy format" );
+            migrateFromLegacy( path );
+        }
+    }
+
+    // Now that we have new data in the JSON structure, load the params again
+    Load();
+
+    // And finally load any nested settings
+    for( auto settings : m_nested_settings )
+        settings->LoadFromFile();
+
+    wxLogTrace( traceSettings, "Loaded %s with schema %d", GetFilename(), m_schemaVersion );
+
+    // If we migrated, clean up the legacy file (with no extension)
+    if( migrated )
+    {
+        if( !wxRemoveFile( path.GetFullPath() ) )
+        {
+            wxLogTrace(
+                    traceSettings, "Warning: could not remove legacy file %s", path.GetFullPath() );
+        }
+
+        // And write-out immediately so that we don't lose data if the program later crashes.
+        SaveToFile( aDirectory );
+    }
+}
+
+
+void JSON_SETTINGS::Store()
+{
+    for( auto param : m_params )
+        param->Store( this );
+}
+
+
+void JSON_SETTINGS::ResetToDefaults()
+{
+    for( auto param : m_params )
+        param->SetDefault();
+}
+
+
+void JSON_SETTINGS::SaveToFile( const std::string& aDirectory )
+{
+    if( !m_writeFile )
+        return;
+
+    wxLogTrace( traceSettings, "Saving %s", m_filename );
+
+    wxFileName path( aDirectory, m_filename, "json" );
+
+    if( !m_createIfMissing && !path.FileExists() )
+        return;
+
+    if( !path.DirExists() && !path.Mkdir() )
+    {
+        wxLogTrace( traceSettings, "Warning: could not create path %s, can't save %s",
+                path.GetPath(), m_filename );
+        return;
+    }
+
+    for( auto settings : m_nested_settings )
+        settings->SaveToFile();
+
+    Store();
+
+    LOCALE_IO dummy;
+
+    try
+    {
+        std::ofstream file( path.GetFullPath().ToStdString() );
+        file << std::setw( 2 ) << *this << std::endl;
+    }
+    catch( const std::exception& e )
+    {
+        wxLogTrace( traceSettings, "Warning: could not save %s: %s", m_filename, e.what() );
+    }
+    catch( ... )
+    {
+    }
+}
+
+
+nlohmann::json JSON_SETTINGS::GetJson( std::string aPath ) const
+{
+    nlohmann::json ret( {} );
+
+    // Will throw an exception if the path is not found
+    try
+    {
+        ret = this->at( PointerFromString( std::move( aPath ) ) );
+    }
+    catch( ... )
+    {
+    }
+
+    return ret;
+}
+
+
+bool JSON_SETTINGS::Migrate()
+{
+    wxLogTrace( traceSettings, "Migrate() not implemented for %s", typeid( *this ).name() );
+    return false;
+}
+
+
+bool JSON_SETTINGS::MigrateFromLegacy( wxConfigBase* aLegacyConfig )
+{
+    wxLogTrace( traceSettings,
+            "MigrateFromLegacy() not implemented for %s", typeid( *this ).name() );
+    return false;
+}
+
+
+nlohmann::json::json_pointer JSON_SETTINGS::PointerFromString( std::string aPath )
+{
+    boost::replace_all( aPath, ".", "/" );
+    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;
+}
+
+
+template<typename ValueType>
+bool JSON_SETTINGS::fromLegacy( wxConfigBase* aConfig, const std::string& aKey,
+                             const std::string& aDest )
+{
+    ValueType val;
+
+    if( aConfig->Read( aKey, &val ) )
+    {
+        try
+        {
+            ( *this )[PointerFromString( aDest )] = val;
+        }
+        catch( ... )
+        {
+            wxASSERT_MSG( false, wxT( "Could not write value in fromLegacy!" ) );
+            return false;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+
+// Explicitly declare these because we only support a few types anyway, and it means we can keep
+// wxConfig detail out of the header file
+template bool JSON_SETTINGS::fromLegacy<int>( wxConfigBase*, const std::string&,
+                                              const std::string& );
+
+template bool JSON_SETTINGS::fromLegacy<double>( wxConfigBase*, const std::string&,
+                                              const std::string& );
+
+template bool JSON_SETTINGS::fromLegacy<bool>( wxConfigBase*, const std::string&,
+                                               const std::string& );
+
+
+bool JSON_SETTINGS::fromLegacyString( wxConfigBase* aConfig, const std::string& aKey,
+                                      const std::string& aDest )
+{
+    wxString str;
+
+    if( aConfig->Read( aKey, &str ) )
+    {
+        try
+        {
+            ( *this )[PointerFromString( aDest )] = str.ToUTF8();
+        }
+        catch( ... )
+        {
+            wxASSERT_MSG( false, wxT( "Could not write value in fromLegacyString!" ) );
+            return false;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+
+bool JSON_SETTINGS::fromLegacyColor( wxConfigBase* aConfig, const std::string& aKey,
+    const std::string& aDest )
+{
+    wxString str;
+
+    if( aConfig->Read( aKey, &str ) )
+    {
+        KIGFX::COLOR4D color;
+        color.SetFromWxString( str );
+
+        try
+        {
+            nlohmann::json js = nlohmann::json::array( { color.r, color.g, color.b, color.a } );
+            ( *this )[PointerFromString( aDest )] = js;
+        }
+        catch( ... )
+        {
+            wxASSERT_MSG( false, wxT( "Could not write value in fromLegacyColor!" ) );
+            return false;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+
+void JSON_SETTINGS::AddNestedSettings( NESTED_SETTINGS* aSettings )
+{
+    m_nested_settings.push_back( aSettings );
+}
+
+
+// Specializations to allow conversion between wxString and std::string via JSON_SETTINGS API
+
+template<> wxString JSON_SETTINGS::Get( std::string aPath ) const
+{
+    return wxString( GetJson( std::move( aPath ) ).get<std::string>().c_str(), wxConvUTF8 );
+}
+
+
+template<> void JSON_SETTINGS::Set<wxString>( std::string aPath, wxString aVal )
+{
+    ( *this )[PointerFromString( std::move( aPath ) ) ] = aVal.ToUTF8();
+}
+
+// Specializations to allow directly reading/writing wxStrings from JSON
+
+void to_json( nlohmann::json& aJson, const wxString& aString )
+{
+    aJson = aString.ToUTF8();
+}
+
+
+void from_json( const nlohmann::json& aJson, wxString& aString )
+{
+    aString = wxString( aJson.get<std::string>().c_str(), wxConvUTF8 );
+}
\ No newline at end of file
diff --git a/common/settings/nested_settings.cpp b/common/settings/nested_settings.cpp
new file mode 100644
index 0000000000..d181c9ea8d
--- /dev/null
+++ b/common/settings/nested_settings.cpp
@@ -0,0 +1,78 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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/log.h>
+
+#include <settings/nested_settings.h>
+
+extern const char* traceSettings;
+
+
+NESTED_SETTINGS::NESTED_SETTINGS( const std::string& aName, int aVersion, JSON_SETTINGS* aParent,
+                                  const std::string& aPath, nlohmann::json aDefault ) :
+        JSON_SETTINGS( aName, SETTINGS_LOC::NESTED, aVersion, std::move( aDefault ) ),
+        m_parent( aParent ), m_path( aPath )
+{
+    wxASSERT( m_parent );
+    m_parent->AddNestedSettings( this );
+
+    // In case we were created after the parent's ctor
+    LoadFromFile();
+}
+
+
+void NESTED_SETTINGS::LoadFromFile( const std::string& aDirectory )
+{
+    clear();
+
+    try
+    {
+        update( ( *m_parent )[PointerFromString( m_path ) ] );
+
+        wxLogTrace( traceSettings, "Loaded NESTED_SETTINGS %s with schema %d",
+                GetFilename(), m_schemaVersion );
+    }
+    catch( ... )
+    {
+        wxLogTrace( traceSettings, "NESTED_SETTINGS %s: Could not load from %s at %s",
+                m_filename, m_parent->GetFilename(), m_path );
+    }
+
+    Load();
+}
+
+
+void NESTED_SETTINGS::SaveToFile( const std::string& aDirectory )
+{
+    Store();
+
+    try
+    {
+        ( *m_parent )[PointerFromString( m_path ) ].update( *this );
+
+        wxLogTrace( traceSettings, "Stored NESTED_SETTINGS %s with schema %d",
+                    GetFilename(), m_schemaVersion );
+    }
+    catch( ... )
+    {
+        wxLogTrace( traceSettings, "NESTED_SETTINGS %s: Could not store to %s at %s",
+                    m_filename, m_parent->GetFilename(), m_path );
+    }
+}
diff --git a/common/settings/settings_manager.cpp b/common/settings/settings_manager.cpp
new file mode 100644
index 0000000000..c1699eb62b
--- /dev/null
+++ b/common/settings/settings_manager.cpp
@@ -0,0 +1,545 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 <regex>
+#include <wx/debug.h>
+#include <wx/filename.h>
+#include <wx/stdpaths.h>
+#include <wx/utils.h>
+
+#include <build_version.h>
+#include <confirm.h>
+#include <dialogs/dialog_migrate_settings.h>
+#include <gestfich.h>
+#include <macros.h>
+#include <settings/app_settings.h>
+#include <settings/common_settings.h>
+#include <settings/settings_manager.h>
+#include <settings/color_settings.h>
+
+
+/**
+ * Flag to enable settings tracing
+ * @ingroup trace_env_vars
+ */
+const char* traceSettings = "SETTINGS";
+
+
+SETTINGS_MANAGER::SETTINGS_MANAGER() :
+        m_common_settings( nullptr ), m_migration_source()
+{
+    // Check if the settings directory already exists, and if not, perform a migration if possible
+    if( !MigrateIfNeeded() )
+    {
+        m_ok = false;
+        return;
+    }
+
+    m_ok = true;
+
+    // create the common settings shared by all applications.  Not loaded immediately
+    m_common_settings =
+            static_cast<COMMON_SETTINGS*>( RegisterSettings( new COMMON_SETTINGS, false ) );
+
+    // create the default color settings
+    m_color_settings["default"] =
+            static_cast<COLOR_SETTINGS*>( RegisterSettings( new COLOR_SETTINGS ) );
+}
+
+SETTINGS_MANAGER::~SETTINGS_MANAGER()
+{
+    m_settings.clear();
+    m_color_settings.clear();
+}
+
+
+JSON_SETTINGS* SETTINGS_MANAGER::RegisterSettings( JSON_SETTINGS* aSettings, bool aLoadNow )
+{
+    std::unique_ptr<JSON_SETTINGS> ptr( aSettings );
+
+    wxLogTrace( traceSettings, "Registered new settings object %s", ptr->GetFilename() );
+
+    if( aLoadNow )
+        ptr->LoadFromFile( GetPathForSettingsFile( ptr.get() ) );
+
+    m_settings.push_back( std::move( ptr ) );
+    return m_settings.back().get();
+}
+
+
+void SETTINGS_MANAGER::Load()
+{
+    // TODO(JE) We should check for dirty settings here and write them if so, because
+    // Load() could be called late in the application lifecycle
+
+    for( auto&& settings : m_settings )
+        settings->LoadFromFile( GetPathForSettingsFile( settings.get() ) );
+}
+
+
+void SETTINGS_MANAGER::Load( JSON_SETTINGS* aSettings )
+{
+    auto it = std::find_if( m_settings.begin(), m_settings.end(),
+                            [&aSettings]( const std::unique_ptr<JSON_SETTINGS>& aPtr ) {
+                              return aPtr.get() == aSettings;
+                            } );
+
+    if( it != m_settings.end() )
+        ( *it )->LoadFromFile( GetPathForSettingsFile( it->get() ) );
+}
+
+
+void SETTINGS_MANAGER::Save()
+{
+    for( auto&& settings : m_settings )
+    {
+        // Never automatically save color settings, caller should use SaveColorSettings
+        if( dynamic_cast<COLOR_SETTINGS*>( settings.get() ) )
+            continue;
+
+        settings->SaveToFile( GetPathForSettingsFile( settings.get() ) );
+    }
+}
+
+
+void SETTINGS_MANAGER::Save( JSON_SETTINGS* aSettings )
+{
+    auto it = std::find_if( m_settings.begin(), m_settings.end(),
+                            [&aSettings]( const std::unique_ptr<JSON_SETTINGS>& aPtr ) {
+                              return aPtr.get() == aSettings;
+                            } );
+
+    if( it != m_settings.end() )
+    {
+        wxLogTrace( traceSettings, "Saving %s", ( *it )->GetFilename() );
+        ( *it )->SaveToFile( GetPathForSettingsFile( it->get() ) );
+    }
+}
+
+
+void SETTINGS_MANAGER::FlushAndRelease( JSON_SETTINGS* aSettings )
+{
+    auto it = std::find_if( m_settings.begin(), m_settings.end(),
+            [&aSettings]( const std::unique_ptr<JSON_SETTINGS>& aPtr ) {
+                return aPtr.get() == aSettings;
+            } );
+
+    if( it != m_settings.end() )
+    {
+        wxLogTrace( traceSettings, "Flush and release %s", ( *it )->GetFilename() );
+        ( *it )->SaveToFile( GetPathForSettingsFile( it->get() ) );
+        m_settings.erase( it );
+    }
+}
+
+
+COLOR_SETTINGS* SETTINGS_MANAGER::GetColorSettings( std::string aName )
+{
+    COLOR_SETTINGS* ret = nullptr;
+
+    try
+    {
+        ret = m_color_settings.at( aName );
+    }
+    catch( std::out_of_range& )
+    {
+        // This had better work
+        ret = m_color_settings.at( "default" );
+    }
+
+    return ret;
+}
+
+
+void SETTINGS_MANAGER::SaveColorSettings( COLOR_SETTINGS* aSettings, const std::string& aNamespace )
+{
+    // The passed settings should already be managed
+    wxASSERT( std::find_if( m_color_settings.begin(), m_color_settings.end(),
+                            [aSettings] ( const auto& el ) {
+                                return el.second == aSettings;
+                            } ) != m_color_settings.end() );
+
+    nlohmann::json::json_pointer ptr = JSON_SETTINGS::PointerFromString( aNamespace );
+
+    aSettings->Store();
+
+    wxASSERT( aSettings->contains( ptr ) );
+
+    wxLogTrace( traceSettings, "Saving color scheme %s, preserving &s",
+            aSettings->GetFilename(), aNamespace );
+
+    nlohmann::json backup = aSettings->at( ptr );
+    std::string path = GetColorSettingsPath();
+
+    aSettings->LoadFromFile( path );
+
+    ( *aSettings )[ptr].update( backup );
+    aSettings->Load();
+
+    aSettings->SaveToFile( path );
+}
+
+
+std::string SETTINGS_MANAGER::GetPathForSettingsFile( JSON_SETTINGS* aSettings )
+{
+    wxASSERT( aSettings );
+
+    switch( aSettings->GetLocation() )
+    {
+    case SETTINGS_LOC::USER:
+        return GetUserSettingsPath();
+
+    case SETTINGS_LOC::PROJECT:
+        // TODO(JE)
+        return "";
+
+    case SETTINGS_LOC::COLORS:
+        return GetColorSettingsPath();
+
+    default:
+        wxASSERT_MSG( false, "Unknown settings location!" );
+    }
+
+    return "";
+}
+
+
+class MIGRATION_TRAVERSER : public wxDirTraverser
+{
+private:
+    wxString m_src;
+    wxString m_dest;
+    wxString m_errors;
+
+public:
+    MIGRATION_TRAVERSER( const wxString& aSrcDir, const wxString& aDestDir ) :
+            m_src( aSrcDir ), m_dest( aDestDir )
+    {
+    }
+
+    wxString GetErrors() { return m_errors; }
+
+    virtual wxDirTraverseResult OnFile( const wxString& aSrcFilePath ) override
+    {
+        wxFileName file( aSrcFilePath );
+        wxString path = file.GetPath();
+
+        path.Replace( m_src, m_dest, false );
+        file.SetPath( path );
+
+        wxLogTrace( traceSettings, "Copying %s to %s", aSrcFilePath, file.GetFullPath() );
+
+        // For now, just copy everything
+        CopyFile( aSrcFilePath, file.GetFullPath(), m_errors );
+
+        return wxDIR_CONTINUE;
+    }
+
+    virtual wxDirTraverseResult OnDir( const wxString& dirPath ) override
+    {
+        wxFileName dir( dirPath );
+
+        // Whitelist of directories to migrate
+        if( dir.GetName() == "colors" ||
+            dir.GetName() == "3d" )
+        {
+
+            wxString path = dir.GetPath();
+
+            path.Replace( m_src, m_dest, false );
+            dir.SetPath( path );
+
+            wxMkdir( dir.GetFullPath() );
+
+            return wxDIR_CONTINUE;
+        }
+        else
+        {
+            return wxDIR_IGNORE;
+        }
+    }
+};
+
+
+bool SETTINGS_MANAGER::MigrateIfNeeded()
+{
+    wxFileName path( GetUserSettingsPath(), "" );
+    wxLogTrace( traceSettings, "Using settings path %s", path.GetFullPath() );
+
+    if( path.DirExists() )
+    {
+        wxFileName common = path;
+        common.SetName( "kicad_common" );
+        common.SetExt( "json" );
+
+        if( common.Exists() )
+        {
+            wxLogTrace( traceSettings, "Path exists and has a kicad_common, continuing!" );
+            return true;
+        }
+    }
+
+    // Now we have an empty path, let's figure out what to put in it
+    DIALOG_MIGRATE_SETTINGS dlg( this );
+
+    if( dlg.ShowModal() != wxID_OK )
+    {
+        wxLogTrace( traceSettings, "Migration dialog canceled; exiting" );
+        return false;
+    }
+
+    if( !path.DirExists() )
+    {
+        wxLogTrace( traceSettings, "Path didn't exist; creating it" );
+        path.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL );
+    }
+
+    if( m_migration_source.IsEmpty() )
+    {
+        wxLogTrace( traceSettings, "No migration source given; starting with defaults" );
+        return true;
+    }
+
+    MIGRATION_TRAVERSER traverser( m_migration_source, path.GetFullPath() );
+    wxDir source_dir( m_migration_source );
+
+    source_dir.Traverse( traverser );
+
+    if( !traverser.GetErrors().empty() )
+        DisplayErrorMessage( nullptr, traverser.GetErrors() );
+
+    return true;
+}
+
+
+bool SETTINGS_MANAGER::GetPreviousVersionPaths( std::vector<wxString>* aPaths )
+{
+    wxASSERT( aPaths );
+
+    aPaths->clear();
+
+    wxDir dir;
+    std::vector<wxFileName> base_paths;
+
+    base_paths.emplace_back( wxFileName( calculateUserSettingsPath( false ), "" ) );
+
+    // If the env override is set, also check the default paths
+    if( wxGetEnv( wxT( "KICAD_CONFIG_HOME" ), nullptr ) )
+        base_paths.emplace_back( wxFileName( calculateUserSettingsPath( false, false ), "" ) );
+
+    wxString subdir;
+    std::string mine = GetSettingsVersion();
+
+    auto check_dir = [&] ( const wxString& aSubDir )
+    {
+        // Only older versions are valid for migration
+        if( compareVersions( aSubDir.ToStdString(), mine ) <= 0 )
+        {
+            wxString sub_path = dir.GetNameWithSep() + aSubDir;
+
+            if( IsSettingsPathValid( sub_path ) )
+            {
+                aPaths->push_back( sub_path );
+                wxLogTrace( traceSettings, "GetPreviousVersionName: %s is valid", sub_path );
+            }
+        }
+    };
+
+    for( auto base_path : base_paths )
+    {
+        if( !dir.Open( base_path.GetFullPath() ) )
+        {
+            wxLogTrace( traceSettings, "GetPreviousVersionName: could not open base path %s",
+                    base_path.GetFullPath() );
+            continue;
+        }
+
+        wxLogTrace( traceSettings, "GetPreviousVersionName: checking base path %s",
+            base_path.GetFullPath() );
+
+        if( dir.GetFirst( &subdir, wxEmptyString, wxDIR_DIRS ) )
+        {
+            if( subdir != mine )
+                check_dir( subdir );
+
+            while( dir.GetNext( &subdir ) )
+            {
+                if( subdir != mine )
+                    check_dir( subdir );
+            }
+        }
+
+        // If we didn't find one yet, check for legacy settings without a version directory
+        if( IsSettingsPathValid( dir.GetNameWithSep() ) )
+        {
+            wxLogTrace( traceSettings,
+                    "GetPreviousVersionName: root path %s is valid", dir.GetName() );
+            aPaths->push_back( dir.GetName() );
+        }
+    }
+
+    return aPaths->size() > 0;
+}
+
+
+bool SETTINGS_MANAGER::IsSettingsPathValid( const wxString& aPath )
+{
+    wxFileName test( aPath, "kicad_common" );
+    return test.Exists();
+}
+
+
+std::string SETTINGS_MANAGER::GetColorSettingsPath()
+{
+    wxFileName path;
+
+    path.AssignDir( GetUserSettingsPath() );
+    path.AppendDir( "colors" );
+
+    return path.GetPath().ToStdString();
+}
+
+
+std::string SETTINGS_MANAGER::GetUserSettingsPath()
+{
+    static std::string user_settings_path;
+
+    if( user_settings_path.empty() )
+        user_settings_path = calculateUserSettingsPath();
+
+    return user_settings_path;
+}
+
+
+std::string SETTINGS_MANAGER::calculateUserSettingsPath( bool aIncludeVer, bool aUseEnv )
+{
+    wxFileName cfgpath;
+
+    // http://docs.wxwidgets.org/3.0/classwx_standard_paths.html#a7c7cf595d94d29147360d031647476b0
+    cfgpath.AssignDir( wxStandardPaths::Get().GetUserConfigDir() );
+
+    // GetUserConfigDir() does not default to ~/.config which is the current standard
+    // configuration file location on Linux.  This has been fixed in later versions of wxWidgets.
+#if !defined( __WXMSW__ ) && !defined( __WXMAC__ )
+    wxArrayString dirs = cfgpath.GetDirs();
+
+    if( dirs.Last() != ".config" )
+        cfgpath.AppendDir( ".config" );
+#endif
+
+    wxString envstr;
+
+    // This shouldn't cause any issues on Windows or MacOS.
+    if( wxGetEnv( wxT( "XDG_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
+    {
+        // Override the assignment above with XDG_CONFIG_HOME
+        cfgpath.AssignDir( envstr );
+    }
+
+    cfgpath.AppendDir( TO_STR( KICAD_CONFIG_DIR ) );
+
+    // Use KICAD_CONFIG_HOME to allow the user to force a specific configuration path.
+    if( aUseEnv && wxGetEnv( wxT( "KICAD_CONFIG_HOME" ), &envstr ) && !envstr.IsEmpty() )
+    {
+        // Override the assignment above with KICAD_CONFIG_HOME
+        cfgpath.AssignDir( envstr );
+    }
+
+    if( aIncludeVer )
+        cfgpath.AppendDir( GetSettingsVersion() );
+
+    return cfgpath.GetPath().ToStdString();
+}
+
+
+std::string SETTINGS_MANAGER::GetSettingsVersion()
+{
+    wxString version = GetBuildVersion().BeforeLast( '.' );
+
+    // A full build version looks like (x.y.z-nnn-g1234567) or x.y.z-xxx
+    // We want to extract the x.y portion here
+    if( version.StartsWith( '(' ) )
+        version = version.Mid( 1 );
+
+    return version.ToStdString();
+}
+
+
+int SETTINGS_MANAGER::compareVersions( const std::string& aFirst, const std::string& aSecond )
+{
+    int a_maj = 0;
+    int a_min = 0;
+    int b_maj = 0;
+    int b_min = 0;
+
+    if( !extractVersion( aFirst, &a_maj, &a_min ) || !extractVersion( aSecond, &b_maj, &b_min ) )
+    {
+        wxLogTrace( traceSettings, "compareSettingsVersions: bad input (%s, %s)", aFirst, aSecond );
+        return -1;
+    }
+
+    if( a_maj < b_maj )
+    {
+        return -1;
+    }
+    else if( a_maj > b_maj )
+    {
+        return 1;
+    }
+    else
+    {
+        if( a_min < b_min )
+        {
+            return -1;
+        }
+        else if( a_min > b_min )
+        {
+            return 1;
+        }
+        else
+        {
+            return 0;
+        }
+    }
+}
+
+
+bool SETTINGS_MANAGER::extractVersion( const std::string& aVersionString, int* aMajor, int* aMinor )
+{
+    std::regex  re_version( "(\\d+)\\.(\\d+)" );
+    std::smatch match;
+
+    if( std::regex_match( aVersionString, match, re_version ) )
+    {
+        try
+        {
+            *aMajor = std::stoi( match[1].str() );
+            *aMinor = std::stoi( match[2].str() );
+        }
+        catch( ... )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    return false;
+}
diff --git a/common/single_top.cpp b/common/single_top.cpp
index c4dc755c7a..475e0912e1 100644
--- a/common/single_top.cpp
+++ b/common/single_top.cpp
@@ -46,6 +46,7 @@
 #include <pgm_base.h>
 #include <kiway_player.h>
 #include <confirm.h>
+#include <settings/settings_manager.h>
 
 
 // Only a single KIWAY is supported in this single_top top level component,
@@ -67,7 +68,11 @@ static struct PGM_SINGLE_TOP : public PGM_BASE
     {
         Kiway.OnKiwayEnd();
 
-        SaveCommonSettings();
+        if( m_settings_manager && m_settings_manager->IsOK() )
+        {
+            SaveCommonSettings();
+            m_settings_manager->Save();
+        }
 
         // Destroy everything in PGM_BASE, especially wxSingleInstanceCheckerImpl
         // earlier than wxApp and earlier than static destruction would.
@@ -157,7 +162,13 @@ struct APP_SINGLE_TOP : public wxApp
 
         try
         {
-            return program.OnPgmInit();
+            if( !program.OnPgmInit() )
+            {
+                program.OnPgmExit();
+                return false;
+            }
+
+            return true;
         }
         catch( const std::exception& e )
         {
diff --git a/common/swig/kicad.i b/common/swig/kicad.i
index 46c9fb3bd2..be4ee016b3 100644
--- a/common/swig/kicad.i
+++ b/common/swig/kicad.i
@@ -91,12 +91,13 @@ principle should be easily implemented by adapting the current STL containers.
     #include <bitset>
 
     #include <title_block.h>
-    #include <colors_design_settings.h>
     #include <marker_base.h>
     #include <eda_text.h>
     #include <convert_to_biu.h>
     #include <id.h>
     #include <build_version.h>
+    #include <layers_id_colors_and_visibility.h>
+    #include <settings/settings_manager.h>
 %}
 
 // all the wx wrappers for wxString, wxPoint, wxRect, wxChar ..
@@ -113,11 +114,10 @@ principle should be easily implemented by adapting the current STL containers.
 %include common.h
 %include title_block.h
 %include gal/color4d.h
-%include core/settings.h
-%include colors_design_settings.h
 %include marker_base.h
 %include eda_text.h
 %include build_version.h
+%include settings/settings_manager.h
 
 // Cast time_t to known type for Python
 typedef long time_t;
diff --git a/common/tool/tool_base.cpp b/common/tool/tool_base.cpp
index 3f7c6e4aec..edc04f8bc3 100644
--- a/common/tool/tool_base.cpp
+++ b/common/tool/tool_base.cpp
@@ -60,43 +60,4 @@ EDA_ITEM* TOOL_BASE::getModelInt() const
 void TOOL_BASE::attachManager( TOOL_MANAGER* aManager )
 {
     m_toolMgr = aManager;
-    m_toolSettings = TOOL_SETTINGS( this );
-}
-
-
-TOOL_SETTINGS::TOOL_SETTINGS( TOOL_BASE* aTool ) :
-    m_tool( aTool )
-{
-}
-
-
-TOOL_SETTINGS::~TOOL_SETTINGS()
-{
-}
-
-
-TOOL_SETTINGS& TOOL_BASE::GetSettings()
-{
-    return m_toolSettings;
-}
-
-
-wxString TOOL_SETTINGS::getKeyName( const wxString& aEntryName ) const
-{
-    wxString key( m_tool->GetName() );
-    key += wxT( "." );
-    key += aEntryName;
-    return key;
-}
-
-
-wxConfigBase* TOOL_SETTINGS::getConfigBase() const
-{
-    if( !m_tool )
-        return NULL;
-
-    if( EDA_BASE_FRAME* frame = m_tool->getEditFrame<EDA_BASE_FRAME>() )
-        return frame->config();
-
-    return NULL;
 }
diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp
index 9009449b50..6c76410730 100644
--- a/common/view/wx_view_controls.cpp
+++ b/common/view/wx_view_controls.cpp
@@ -32,6 +32,7 @@
 #include <view/zoom_controller.h>
 #include <gal/graphics_abstraction_layer.h>
 #include <tool/tool_dispatcher.h>
+#include <settings/common_settings.h>
 #include <math/util.h>      // for KiROUND
 
 
@@ -67,13 +68,9 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel
         m_cursorPos( 0, 0 ),
         m_updateCursor( true )
 {
-    bool enableMousewheelPan = false;
-    bool enableZoomNoCenter = false;
-    bool enableAutoPan = true;
-
-    Pgm().CommonSettings()->Read( ENBL_MOUSEWHEEL_PAN_KEY, &enableMousewheelPan, false );
-    Pgm().CommonSettings()->Read( ENBL_ZOOM_NO_CENTER_KEY, &enableZoomNoCenter, false );
-    Pgm().CommonSettings()->Read( ENBL_AUTO_PAN_KEY, &enableAutoPan, true );
+    bool enableMousewheelPan = Pgm().GetCommonSettings()->m_Input.mousewheel_pan;
+    bool enableZoomNoCenter = !Pgm().GetCommonSettings()->m_Input.center_on_zoom;
+    bool enableAutoPan = Pgm().GetCommonSettings()->m_Input.auto_pan;
 
     m_settings.m_enableMousewheelPan = enableMousewheelPan;
     m_settings.m_warpCursor = !enableZoomNoCenter;
@@ -136,13 +133,13 @@ WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, wxScrolledCanvas* aParentPanel
 
 WX_VIEW_CONTROLS::~WX_VIEW_CONTROLS()
 {
-    wxConfigBase* cfg = Pgm().CommonSettings();
+    COMMON_SETTINGS* cfg = Pgm().GetCommonSettings();
 
     if( cfg )
     {
-        cfg->Write( ENBL_MOUSEWHEEL_PAN_KEY, m_settings.m_enableMousewheelPan );
-        cfg->Write( ENBL_ZOOM_NO_CENTER_KEY, !m_settings.m_warpCursor );
-        cfg->Write( ENBL_AUTO_PAN_KEY, m_settings.m_autoPanSettingEnabled );
+        cfg->m_Input.mousewheel_pan = m_settings.m_enableMousewheelPan;
+        cfg->m_Input.center_on_zoom = m_settings.m_warpCursor;
+        cfg->m_Input.auto_pan = m_settings.m_autoPanSettingEnabled;
     }
 }
 
diff --git a/cvpcb/CMakeLists.txt b/cvpcb/CMakeLists.txt
index f2e296ceca..8b7a9d2a41 100644
--- a/cvpcb/CMakeLists.txt
+++ b/cvpcb/CMakeLists.txt
@@ -37,6 +37,7 @@ set( CVPCB_SRCS
     footprints_listbox.cpp
     library_listbox.cpp
     cvpcb_mainframe.cpp
+    cvpcb_settings.cpp
     listbox_base.cpp
     menubar.cpp
     readwrite_dlgs.cpp
diff --git a/cvpcb/cvpcb.cpp b/cvpcb/cvpcb.cpp
index b08ef3f120..825c77814d 100644
--- a/cvpcb/cvpcb.cpp
+++ b/cvpcb/cvpcb.cpp
@@ -31,8 +31,10 @@
 #include <fp_lib_table.h>
 #include <kiface_i.h>
 #include <pgm_base.h>
+#include <settings/settings_manager.h>
 
 #include <cvpcb_mainframe.h>
+#include <cvpcb_settings.h>
 #include <display_footprints_frame.h>
 
 
@@ -128,6 +130,9 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
 
     // Do nothing in here pertinent to a project!
 
+    InitSettings( new CVPCB_SETTINGS );
+    aProgram->GetSettingsManager().RegisterSettings( KifaceSettings() );
+
     start_common( aCtlBits );
 
     /*  Now that there are no *.mod files in the standard library, this function
diff --git a/cvpcb/cvpcb_mainframe.cpp b/cvpcb/cvpcb_mainframe.cpp
index 8699512c2d..e1324df10e 100644
--- a/cvpcb/cvpcb_mainframe.cpp
+++ b/cvpcb/cvpcb_mainframe.cpp
@@ -42,6 +42,7 @@
 #include <cvpcb_association.h>
 #include <cvpcb_id.h>
 #include <cvpcb_mainframe.h>
+#include <cvpcb_settings.h>
 #include <display_footprints_frame.h>
 #include <listboxes.h>
 #include <tools/cvpcb_actions.h>
@@ -51,12 +52,6 @@
 wxSize const FRAME_MIN_SIZE_DU( 400, 300 );
 wxSize const FRAME_DEFAULT_SIZE_DU( 500, 400 );
 
-///@{
-/// \ingroup config
-
-static const wxString FilterFootprintEntry = "FilterFootprint";
-///@}
-
 #define CVPCB_MAINFRAME_NAME wxT( "CvpcbFrame" )
 
 
@@ -376,7 +371,7 @@ void CVPCB_MAINFRAME::OnSelectComponent( wxListEvent& event )
 }
 
 
-void CVPCB_MAINFRAME::LoadSettings( wxConfigBase* aCfg )
+void CVPCB_MAINFRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_BASE_FRAME::LoadSettings( aCfg );
 
@@ -385,15 +380,18 @@ void CVPCB_MAINFRAME::LoadSettings( wxConfigBase* aCfg )
     if( m_FrameSize == wxDefaultSize )
         m_FrameSize = frame_default;
 
-    aCfg->Read( FilterFootprintEntry, &m_filteringOptions, FOOTPRINTS_LISTBOX::UNFILTERED_FP_LIST );
+    auto cfg = static_cast<CVPCB_SETTINGS*>( aCfg );
+
+    m_filteringOptions = cfg->m_FilterFootprint;
 }
 
 
-void CVPCB_MAINFRAME::SaveSettings( wxConfigBase* aCfg )
+void CVPCB_MAINFRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_BASE_FRAME::SaveSettings( aCfg );
 
-    aCfg->Write( FilterFootprintEntry, m_filteringOptions );
+    auto cfg = static_cast<CVPCB_SETTINGS*>( aCfg );
+    cfg->m_FilterFootprint = m_filteringOptions;
 }
 
 
diff --git a/cvpcb/cvpcb_mainframe.h b/cvpcb/cvpcb_mainframe.h
index fe4a6491d2..b769175e82 100644
--- a/cvpcb/cvpcb_mainframe.h
+++ b/cvpcb/cvpcb_mainframe.h
@@ -293,9 +293,9 @@ public:
      */
     void SaveProjectFile();
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
 
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     /**
      * Function DisplayStatus
diff --git a/cvpcb/cvpcb_settings.cpp b/cvpcb/cvpcb_settings.cpp
new file mode 100644
index 0000000000..75824948b6
--- /dev/null
+++ b/cvpcb/cvpcb_settings.cpp
@@ -0,0 +1,68 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#include <cvpcb_settings.h>
+#include <settings/parameters.h>
+#include <wx/config.h>
+
+
+///! Update the schema version whenever a migration is required
+const int cvpcbSchemaVersion = 0;
+
+CVPCB_SETTINGS::CVPCB_SETTINGS() :
+        APP_SETTINGS_BASE( "cvpcb", cvpcbSchemaVersion )
+{
+    m_params.emplace_back( new PARAM<int>( "filter_footprint", &m_FilterFootprint, 0 ) );
+
+    addParamsForWindow( &m_FootprintViewer, "footprint_viewer" );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "footprint_viewer.pad_fill",
+                    &m_FootprintViewerDisplayOptions.m_DisplayPadFill, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "footprint_viewer.pad_numbers",
+            &m_FootprintViewerDisplayOptions.m_DisplayPadNum, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "footprint_viewer.footprint_text_fill",
+            &m_FootprintViewerDisplayOptions.m_DisplayModTextFill, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "footprint_viewer.graphic_items_fill",
+            &m_FootprintViewerDisplayOptions.m_DisplayDrawItemsFill, true ) );
+}
+
+
+bool CVPCB_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacy<int>( aCfg, "FilterFootprint", "filter_footprint" );
+
+    ret &= migrateWindowConfig( aCfg, "FootprintViewerFrame", "footprint_viewer" );
+
+    ret &= fromLegacy<bool>( aCfg, "FootprintViewerFrameDiPadFi", "footprint_viewer.pad_fill" );
+    ret &= fromLegacy<bool>( aCfg, "FootprintViewerFrameDiPadNu", "footprint_viewer.pad_numbers" );
+    ret &= fromLegacy<bool>(
+            aCfg, "FootprintViewerFrameDiModTx", "footprint_viewer.footprint_text_fill" );
+
+    return ret;
+}
diff --git a/cvpcb/cvpcb_settings.h b/cvpcb/cvpcb_settings.h
new file mode 100644
index 0000000000..63a6dba309
--- /dev/null
+++ b/cvpcb/cvpcb_settings.h
@@ -0,0 +1,51 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#ifndef _CVPCB_SETTINGS_H
+#define _CVPCB_SETTINGS_H
+
+#include <pcb_display_options.h>
+#include <settings/app_settings.h>
+
+class CVPCB_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+    CVPCB_SETTINGS();
+
+    virtual ~CVPCB_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    WINDOW_SETTINGS m_FootprintViewer;
+
+    PCB_DISPLAY_OPTIONS m_FootprintViewerDisplayOptions;
+
+    int m_FilterFootprint;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "CvpcbFrame"; }
+};
+
+
+#endif
diff --git a/cvpcb/dialogs/dialog_config_equfiles.cpp b/cvpcb/dialogs/dialog_config_equfiles.cpp
index f5e2754c93..273a6034ac 100644
--- a/cvpcb/dialogs/dialog_config_equfiles.cpp
+++ b/cvpcb/dialogs/dialog_config_equfiles.cpp
@@ -42,7 +42,6 @@ DIALOG_CONFIG_EQUFILES::DIALOG_CONFIG_EQUFILES( CVPCB_MAINFRAME* aParent ) :
     DIALOG_CONFIG_EQUFILES_BASE( aParent )
 {
     m_Parent = aParent;
-    m_Config = Pgm().CommonSettings();
 
     PROJECT&    prj = Prj();
     SetTitle( wxString::Format( _( "Project file: \"%s\"" ),
diff --git a/cvpcb/dialogs/dialog_config_equfiles.h b/cvpcb/dialogs/dialog_config_equfiles.h
index bbe84e2dbc..5a045853b8 100644
--- a/cvpcb/dialogs/dialog_config_equfiles.h
+++ b/cvpcb/dialogs/dialog_config_equfiles.h
@@ -35,7 +35,6 @@ class DIALOG_CONFIG_EQUFILES : public DIALOG_CONFIG_EQUFILES_BASE
 {
 private:
     CVPCB_MAINFRAME* m_Parent;
-    wxConfigBase*    m_Config;
     wxString         m_UserLibDirBufferImg;
 
     bool m_ListChanged;
diff --git a/cvpcb/display_footprints_frame.cpp b/cvpcb/display_footprints_frame.cpp
index c482b05ed7..5e6e4851f1 100644
--- a/cvpcb/display_footprints_frame.cpp
+++ b/cvpcb/display_footprints_frame.cpp
@@ -28,6 +28,7 @@
 #include <class_module.h>
 #include <common.h>
 #include <confirm.h>
+#include <cvpcb_settings.h>
 #include <fp_lib_table.h>
 #include <id.h>
 #include <lib_id.h>
@@ -46,9 +47,6 @@
 #include <tools/cvpcb_fpviewer_control.h>
 #include <tools/cvpcb_fpviewer_selection_tool.h>
 
-// Colors for layers and items
-COLORS_DESIGN_SETTINGS g_ColorsSettings( FRAME_CVPCB_DISPLAY );
-
 
 BEGIN_EVENT_TABLE( DISPLAY_FOOTPRINTS_FRAME, PCB_BASE_FRAME )
     EVT_CLOSE( DISPLAY_FOOTPRINTS_FRAME::OnCloseWindow )
@@ -262,23 +260,39 @@ void DISPLAY_FOOTPRINTS_FRAME::ReCreateHToolbar()
 }
 
 
-void DISPLAY_FOOTPRINTS_FRAME::LoadSettings( wxConfigBase* aCfg )
+void DISPLAY_FOOTPRINTS_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
-    PCB_BASE_FRAME::LoadSettings( aCfg );
+    auto cfg = dynamic_cast<CVPCB_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
 
-    m_configSettings.Load( aCfg );  // mainly, load the color config
+    EDA_DRAW_FRAME::LoadSettings( cfg );
 
-    aCfg->Read( ConfigBaseName() + AUTO_ZOOM_KEY, &m_autoZoom, true );
-    aCfg->Read( ConfigBaseName() + ZOOM_KEY, &m_lastZoom, 10.0 );
+    SetDisplayOptions( cfg->m_FootprintViewerDisplayOptions );
+
+    m_autoZoom = cfg->m_FootprintViewer.auto_zoom;
+    m_lastZoom = cfg->m_FootprintViewer.zoom;
 }
 
 
-void DISPLAY_FOOTPRINTS_FRAME::SaveSettings( wxConfigBase* aCfg )
+void DISPLAY_FOOTPRINTS_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
-    PCB_BASE_FRAME::SaveSettings( aCfg );
+    auto cfg = dynamic_cast<CVPCB_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
 
-    aCfg->Write( ConfigBaseName() + AUTO_ZOOM_KEY, m_autoZoom );
-    aCfg->Write( ConfigBaseName() + ZOOM_KEY, GetCanvas()->GetView()->GetScale() );
+    EDA_DRAW_FRAME::SaveSettings( cfg );
+
+    cfg->m_FootprintViewerDisplayOptions = GetDisplayOptions();
+
+    cfg->m_FootprintViewer.auto_zoom = m_autoZoom;
+    cfg->m_FootprintViewer.zoom      = GetCanvas()->GetView()->GetScale();
+}
+
+
+WINDOW_SETTINGS* DISPLAY_FOOTPRINTS_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
+{
+    auto cfg = dynamic_cast<CVPCB_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+    return &cfg->m_FootprintViewer;
 }
 
 
@@ -401,7 +415,7 @@ void DISPLAY_FOOTPRINTS_FRAME::InitDisplay()
 void DISPLAY_FOOTPRINTS_FRAME::updateView()
 {
     PCB_DRAW_PANEL_GAL* dp = static_cast<PCB_DRAW_PANEL_GAL*>( GetCanvas() );
-    dp->UseColorScheme( &Settings().Colors() );
+    dp->UpdateColors();
     dp->DisplayBoard( GetBoard() );
 
     m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
diff --git a/cvpcb/display_footprints_frame.h b/cvpcb/display_footprints_frame.h
index d7ff734612..48e757996a 100644
--- a/cvpcb/display_footprints_frame.h
+++ b/cvpcb/display_footprints_frame.h
@@ -66,8 +66,10 @@ public:
      */
     void updateView();
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
+
+    WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     /// Updates the GAL with display settings changes
     void ApplyDisplaySettingsToGAL();
diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt
index c9c4423117..00eb51870e 100644
--- a/eeschema/CMakeLists.txt
+++ b/eeschema/CMakeLists.txt
@@ -118,6 +118,7 @@ set( EESCHEMA_WIDGETS
 set ( EESCHEMA_LIBEDIT_SRCS
     libedit/libedit.cpp
     libedit/libedit_plot_component.cpp
+    libedit/libedit_settings.cpp
     libedit/libedit_undo_redo.cpp
     libedit/lib_edit_frame.cpp
     libedit/menubar_libedit.cpp
@@ -147,6 +148,7 @@ set( EESCHEMA_SRCS
     drc_erc_item.cpp
     edit_label.cpp
     eeschema_config.cpp
+    eeschema_settings.cpp
     erc.cpp
     fields_grid_table.cpp
     files-io.cpp
diff --git a/eeschema/autoplace_fields.cpp b/eeschema/autoplace_fields.cpp
index 2aa9a72a64..0435571fa9 100644
--- a/eeschema/autoplace_fields.cpp
+++ b/eeschema/autoplace_fields.cpp
@@ -65,6 +65,7 @@
 #include <algorithm>
 #include <tool/tool_manager.h>
 #include <tools/ee_selection_tool.h>
+#include <eeschema_settings.h>
 
 #define FIELD_PADDING Mils2iu( 10 )            // arbitrarily chosen for aesthetics
 #define FIELD_PADDING_ALIGNED Mils2iu( 18 )    // aligns 50 mil text to a 100 mil grid
@@ -126,8 +127,10 @@ public:
         :m_screen( aScreen ), m_component( aComponent )
     {
         m_component->GetFields( m_fields, /* aVisibleOnly */ true );
-        Kiface().KifaceSettings()->Read( AutoplaceJustifyEntry, &m_allow_rejustify, true );
-        Kiface().KifaceSettings()->Read( AutoplaceAlignEntry, &m_align_to_grid, false );
+
+        auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+        m_allow_rejustify = cfg->m_AutoplaceFields.allow_rejustify;
+        m_align_to_grid = cfg->m_AutoplaceFields.align_to_grid;
 
         m_comp_bbox = m_component->GetBodyBoundingBox();
         m_fbox_size = ComputeFBoxSize( /* aDynamic */ true );
diff --git a/eeschema/connection_graph.cpp b/eeschema/connection_graph.cpp
index 198373d767..591029f8b7 100644
--- a/eeschema/connection_graph.cpp
+++ b/eeschema/connection_graph.cpp
@@ -26,7 +26,6 @@
 #include <unordered_map>
 #include <profile.h>
 
-#include <advanced_config.h>
 #include <common.h>
 #include <erc.h>
 #include <sch_bus_entry.h>
@@ -39,6 +38,7 @@
 #include <sch_sheet.h>
 #include <sch_sheet_path.h>
 #include <sch_text.h>
+#include <advanced_config.h>
 
 #include <connection_graph.h>
 
diff --git a/eeschema/dialogs/dialog_annotate.cpp b/eeschema/dialogs/dialog_annotate.cpp
index dab8a1af61..d8424f5fc6 100644
--- a/eeschema/dialogs/dialog_annotate.cpp
+++ b/eeschema/dialogs/dialog_annotate.cpp
@@ -36,19 +36,14 @@
 
 #include <invoke_sch_dialog.h>
 #include <dialog_annotate_base.h>
+#include <eeschema_settings.h>
 #include <kiface_i.h>
 #include <wx_html_report_panel.h>
 
-#define KEY_ANNOTATE_SORT_OPTION          wxT( "AnnotateSortOption" )
-#define KEY_ANNOTATE_ALGO_OPTION          wxT( "AnnotateAlgoOption" )
-#define KEY_ANNOTATE_MESSAGES_FILTER      wxT( "AnnotateFilterMsg" )
-
 // A window name for the annotate dialog to retrieve is if not destroyed
 #define DLG_WINDOW_NAME "DialogAnnotateWindowName"
 
 
-class wxConfigBase;
-
 /**
  * DIALOG_ANNOTATE: a dialog to set/clear reference designators,
  * of a schematic hierarchy, with different options
@@ -61,7 +56,6 @@ public:
 
 private:
     SCH_EDIT_FRAME* m_Parent;
-    wxConfigBase*   m_Config;
 
     /// Initialises member variables
     void InitValues();
@@ -128,24 +122,24 @@ DIALOG_ANNOTATE::DIALOG_ANNOTATE( SCH_EDIT_FRAME* parent, const wxString& messag
 
 DIALOG_ANNOTATE::~DIALOG_ANNOTATE()
 {
-    m_Config->Write( KEY_ANNOTATE_SORT_OPTION, GetSortOrder() );
-    m_Config->Write( KEY_ANNOTATE_ALGO_OPTION, GetAnnotateAlgo() );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
 
-    m_Config->Write( KEY_ANNOTATE_MESSAGES_FILTER,
-                    (long) m_MessageWindow->GetVisibleSeverities() );
+    cfg->m_AnnotatePanel.sort_order = GetSortOrder();
+    cfg->m_AnnotatePanel.method = GetAnnotateAlgo();
+    cfg->m_AnnotatePanel.messages_filter = m_MessageWindow->GetVisibleSeverities();
 }
 
 
 void DIALOG_ANNOTATE::InitValues()
 {
-    m_Config = Kiface().KifaceSettings();
-    long option;
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+    int option;
 
     // These are always reset to attempt to keep the user out of trouble...
     m_rbScope->SetSelection( 0 );
     m_rbOptions->SetSelection( 0 );
 
-    m_Config->Read( KEY_ANNOTATE_SORT_OPTION, &option, 0L );
+    option = cfg->m_AnnotatePanel.sort_order;
 
     switch( option )
     {
@@ -158,7 +152,7 @@ void DIALOG_ANNOTATE::InitValues()
         break;
     }
 
-    m_Config->Read( KEY_ANNOTATE_ALGO_OPTION, &option, 0L );
+    option = cfg->m_AnnotatePanel.method;
 
     switch( option )
     {
@@ -179,8 +173,7 @@ void DIALOG_ANNOTATE::InitValues()
     annotate_down_right_bitmap->SetBitmap( KiBitmap( annotate_down_right_xpm ) );
     annotate_right_down_bitmap->SetBitmap( KiBitmap( annotate_right_down_xpm ) );
 
-    int severities = m_Config->Read( KEY_ANNOTATE_MESSAGES_FILTER, -1l );
-    m_MessageWindow->SetVisibleSeverities( severities );
+    m_MessageWindow->SetVisibleSeverities( cfg->m_AnnotatePanel.messages_filter );
 
     m_MessageWindow->MsgPanelSetMinSize( wxSize( -1, 160 ) );
 }
diff --git a/eeschema/dialogs/dialog_bom.cpp b/eeschema/dialogs/dialog_bom.cpp
index d012ab00ed..c966ee8a95 100644
--- a/eeschema/dialogs/dialog_bom.cpp
+++ b/eeschema/dialogs/dialog_bom.cpp
@@ -28,29 +28,27 @@
  */
 
 
-#include <fctsys.h>
-#include <pgm_base.h>
-#include <kiface_i.h>
+#include <bom_plugins.h>
 #include <confirm.h>
+#include <dialog_bom_base.h>
+#include <dialog_helpers.h>
+#include <eeschema_settings.h>
+#include <fctsys.h>
 #include <gestfich.h>
-#include <sch_edit_frame.h>
+#include <html_messagebox.h>
+#include <i18n_utility.h> // for _HKI definition used in dialog_bom_help_md.h
+#include <invoke_sch_dialog.h>
+#include <kiface_i.h>
 #include <netlist.h>
 #include <netlist_exporter_generic.h>
-#include <invoke_sch_dialog.h>
-#include <dialog_helpers.h>
-#include <dialog_bom_base.h>
-#include <html_messagebox.h>
+#include <pgm_base.h>
 #include <reporter.h>
-#include <bom_plugins.h>
-#include <i18n_utility.h>   // for _HKI definition used in dialog_bom_help_md.h
+#include <sch_edit_frame.h>
 
 #include <dialogs/dialog_bom_cfg_lexer.h>
 
 static constexpr wxChar BOM_TRACE[] = wxT( "BOM_GENERATORS" );
 
-static constexpr wxChar BOM_GENERATORS_KEY[] = wxT( "bom_plugins" );
-static constexpr wxChar BOM_GENERATOR_SELECTED_KEY[] =  wxT( "bom_plugin_selected" );
-
 wxString s_bomHelpInfo =
 #include <dialog_bom_help_md.h>
 ;
@@ -175,7 +173,6 @@ class DIALOG_BOM : public DIALOG_BOM_BASE
 private:
     SCH_EDIT_FRAME*   m_parent;
     BOM_GENERATOR_ARRAY  m_generators;
-    wxConfigBase*     m_config;         // to store the "plugins"
     bool              m_initialized;
 
 public:
@@ -225,7 +222,6 @@ DIALOG_BOM::DIALOG_BOM( SCH_EDIT_FRAME* parent ) :
     DIALOG_BOM_BASE( parent )
 {
     m_parent = parent;
-    m_config = Kiface().KifaceSettings();
     m_initialized = false;
 
     m_buttonAddGenerator->SetBitmap( KiBitmap( small_plus_xpm ) );
@@ -251,6 +247,8 @@ DIALOG_BOM::DIALOG_BOM( SCH_EDIT_FRAME* parent ) :
 
 DIALOG_BOM::~DIALOG_BOM()
 {
+    // TODO(JE) maybe unpack this into JSON instead of sexpr
+
     // Save the plugin descriptions in config.
     // The config stores only one string, so we save the plugins inside a S-expr:
     // ( plugins
@@ -289,19 +287,20 @@ DIALOG_BOM::~DIALOG_BOM()
 
     wxString list( FROM_UTF8( writer.GetString().c_str() ) );
 
-    m_config->Write( BOM_GENERATORS_KEY, list );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
 
-    wxString active_plugin_name = m_lbGenerators->GetStringSelection( );
-    m_config->Write( BOM_GENERATOR_SELECTED_KEY, active_plugin_name );
+    cfg->m_BomPanel.plugins = list.ToStdString();
+    cfg->m_BomPanel.selected_plugin = m_lbGenerators->GetStringSelection().ToStdString();
 }
 
 
 // Read the initialized plugins in config and fill the list of names
 void DIALOG_BOM::installGeneratorsList()
 {
-    wxString list, active_plugin_name;
-    m_config->Read( BOM_GENERATORS_KEY, &list );
-    m_config->Read( BOM_GENERATOR_SELECTED_KEY, &active_plugin_name );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+
+    wxString list               = cfg->m_BomPanel.plugins;
+    wxString active_plugin_name = cfg->m_BomPanel.selected_plugin;
 
     if( !list.IsEmpty() )
     {
diff --git a/eeschema/dialogs/dialog_choose_component.cpp b/eeschema/dialogs/dialog_choose_component.cpp
index 09a0917373..14385b7240 100644
--- a/eeschema/dialogs/dialog_choose_component.cpp
+++ b/eeschema/dialogs/dialog_choose_component.cpp
@@ -22,26 +22,27 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <dialog_choose_component.h>
 #include <algorithm>
-#include <wx/utils.h>
+#include <class_libentry.h>
+#include <class_library.h>
+#include <dialog_choose_component.h>
+#include <eeschema_settings.h>
+#include <kiface_i.h>
+#include <sch_base_frame.h>
+#include <symbol_lib_table.h>
+#include <template_fieldnames.h>
+#include <widgets/footprint_preview_widget.h>
+#include <widgets/footprint_select_widget.h>
+#include <widgets/lib_tree.h>
+#include <widgets/symbol_preview_widget.h>
 #include <wx/button.h>
+#include <wx/clipbrd.h>
 #include <wx/dataview.h>
 #include <wx/panel.h>
 #include <wx/sizer.h>
 #include <wx/splitter.h>
 #include <wx/timer.h>
-#include <class_library.h>
-#include <sch_base_frame.h>
-#include <template_fieldnames.h>
-#include <symbol_lib_table.h>
-#include <widgets/lib_tree.h>
-#include <widgets/footprint_preview_widget.h>
-#include <widgets/footprint_select_widget.h>
-#include <widgets/symbol_preview_widget.h>
-#include <wx/clipbrd.h>
-#include <kiface_i.h>
-#include <class_libentry.h>
+#include <wx/utils.h>
 
 #define SYM_CHOOSER_HSASH           wxT( "SymbolChooserHSashPosition" )
 #define SYM_CHOOSER_VSASH           wxT( "SymbolChooserVSashPosition" )
@@ -73,8 +74,6 @@ DIALOG_CHOOSE_COMPONENT::DIALOG_CHOOSE_COMPONENT( SCH_BASE_FRAME* aParent, const
           m_show_footprints( aShowFootprints ),
           m_external_browser_requested( false )
 {
-    m_config = Kiface().KifaceSettings();
-
     auto sizer = new wxBoxSizer( wxVERTICAL );
 
     // Use a slightly different layout, with a details pane spanning the entire window,
@@ -148,16 +147,21 @@ DIALOG_CHOOSE_COMPONENT::DIALOG_CHOOSE_COMPONENT( SCH_BASE_FRAME* aParent, const
 
     Layout();
 
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+
     // We specify the width of the right window (m_symbol_view_panel), because specify
     // the width of the left window does not work as expected when SetSashGravity() is called
-    m_hsplitter->SetSashPosition( m_config->Read( SYM_CHOOSER_HSASH, HorizPixelsFromDU( 220 ) ) );
+    m_hsplitter->SetSashPosition( cfg->m_SymChooserPanel.sash_pos_h > 0 ?
+                                  cfg->m_SymChooserPanel.sash_pos_h : HorizPixelsFromDU( 220 ) );
 
     if( m_vsplitter )
-        m_vsplitter->SetSashPosition( m_config->Read( SYM_CHOOSER_VSASH,
-                                                      VertPixelsFromDU( 230 ) ) );
+        m_vsplitter->SetSashPosition( cfg->m_SymChooserPanel.sash_pos_v > 0 ?
+                                      cfg->m_SymChooserPanel.sash_pos_v : VertPixelsFromDU( 230 ) );
 
-    wxSize dlgSize( m_config->Read( SYM_CHOOSER_WIDTH_KEY, HorizPixelsFromDU( 390 ) ),
-                    m_config->Read( SYM_CHOOSER_HEIGHT_KEY, VertPixelsFromDU( 300 ) ) );
+    wxSize dlgSize( cfg->m_SymChooserPanel.width > 0 ?
+                    cfg->m_SymChooserPanel.width : HorizPixelsFromDU( 390 ),
+                    cfg->m_SymChooserPanel.height > 0 ?
+                    cfg->m_SymChooserPanel.height : VertPixelsFromDU( 300 ) );
     SetSize( dlgSize );
 
     SetInitialFocus( m_tree );
@@ -207,16 +211,18 @@ DIALOG_CHOOSE_COMPONENT::~DIALOG_CHOOSE_COMPONENT()
     m_dbl_click_timer->Stop();
     delete m_dbl_click_timer;
 
-    m_config->Write( SYM_CHOOSER_WIDTH_KEY, GetSize().x );
-    m_config->Write( SYM_CHOOSER_HEIGHT_KEY, GetSize().y );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
 
-    m_config->Write( SYM_CHOOSER_KEEP_SYM_KEY, m_keepSymbol->GetValue() );
-    m_config->Write( SYM_CHOOSER_USE_UNITS_KEY, m_useUnits->GetValue() );
+    cfg->m_SymChooserPanel.width = GetSize().x;
+    cfg->m_SymChooserPanel.height = GetSize().y;
 
-    m_config->Write( SYM_CHOOSER_HSASH, m_hsplitter->GetSashPosition() );
+    cfg->m_SymChooserPanel.keep_symbol = m_keepSymbol->GetValue();
+    cfg->m_SymChooserPanel.place_all_units = m_useUnits->GetValue();
+
+    cfg->m_SymChooserPanel.sash_pos_h = m_hsplitter->GetSashPosition();
 
     if( m_vsplitter )
-        m_config->Write( SYM_CHOOSER_VSASH, m_vsplitter->GetSashPosition() );
+        cfg->m_SymChooserPanel.sash_pos_v = m_vsplitter->GetSashPosition();
 }
 
 
@@ -254,14 +260,16 @@ wxPanel* DIALOG_CHOOSE_COMPONENT::ConstructRightPanel( wxWindow* aParent )
         sizer->Add( m_symbol_preview, 1, wxEXPAND | wxTOP | wxRIGHT, 5 );
     }
 
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+
     m_keepSymbol = new wxCheckBox( panel, 1000, _("Multi-Symbol Placement"), wxDefaultPosition,
             wxDefaultSize, wxALIGN_RIGHT );
-    m_keepSymbol->SetValue( m_config->ReadBool( SYM_CHOOSER_KEEP_SYM_KEY, false ) );
+    m_keepSymbol->SetValue( cfg->m_SymChooserPanel.keep_symbol );
     m_keepSymbol->SetToolTip( _( "Place multiple copies of the symbol." ) );
 
     m_useUnits = new wxCheckBox( panel, 1000, _("Place all units"), wxDefaultPosition,
             wxDefaultSize, wxALIGN_RIGHT );
-    m_useUnits->SetValue( m_config->ReadBool( SYM_CHOOSER_USE_UNITS_KEY, true ) );
+    m_useUnits->SetValue( cfg->m_SymChooserPanel.place_all_units );
     m_useUnits->SetToolTip( _( "Sequentially place all units of the symbol." ) );
 
     auto fgSizer = new wxFlexGridSizer( 0, 2, 0, 1 );
diff --git a/eeschema/dialogs/dialog_choose_component.h b/eeschema/dialogs/dialog_choose_component.h
index 3186bae98c..24666eba5a 100644
--- a/eeschema/dialogs/dialog_choose_component.h
+++ b/eeschema/dialogs/dialog_choose_component.h
@@ -200,8 +200,6 @@ protected:
      */
     void PopulateFootprintSelector( LIB_ID const& aLibId );
 
-    wxConfigBase*             m_config;
-
     wxTimer*                  m_dbl_click_timer;
     SYMBOL_PREVIEW_WIDGET*    m_symbol_preview;
     wxButton*                 m_browser_button;
diff --git a/eeschema/dialogs/dialog_edit_component_in_lib.cpp b/eeschema/dialogs/dialog_edit_component_in_lib.cpp
index de4e9636b4..4f116718a4 100644
--- a/eeschema/dialogs/dialog_edit_component_in_lib.cpp
+++ b/eeschema/dialogs/dialog_edit_component_in_lib.cpp
@@ -21,26 +21,26 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <kiway.h>
+#include <bitmaps.h>
+#include <class_libentry.h>
 #include <common.h>
 #include <confirm.h>
-#include <pgm_base.h>
-#include <kiface_i.h>
+#include <dialog_helpers.h>
 #include <dialog_text_entry.h>
-#include <math/util.h>      // for KiROUND
-
+#include <eeschema_settings.h>
+#include <fctsys.h>
 #include <general.h>
-#include <widgets/wx_grid.h>
-#include <widgets/grid_text_button_helpers.h>
+#include <kiface_i.h>
+#include <kiway.h>
 #include <lib_edit_frame.h>
 #include <lib_manager.h>
-#include <class_libentry.h>
-#include <symbol_lib_table.h>
-#include <sch_item.h>
+#include <math/util.h> // for KiROUND
+#include <pgm_base.h>
 #include <sch_component.h>
-#include <dialog_helpers.h>
-#include <bitmaps.h>
+#include <sch_item.h>
+#include <symbol_lib_table.h>
+#include <widgets/grid_text_button_helpers.h>
+#include <widgets/wx_grid.h>
 
 #ifdef KICAD_SPICE
 #include <dialog_spice_model.h>
@@ -48,10 +48,10 @@
 #endif /* KICAD_SPICE */
 
 #include <dialog_edit_component_in_lib.h>
+#include <settings/settings_manager.h>
+#include <libedit_settings.h>
 
 
-#define LibEditFieldsShownColumnsKey   wxT( "LibEditFieldsShownColumns" )
-
 int DIALOG_EDIT_COMPONENT_IN_LIBRARY::m_lastOpenedPage = 0;
 DIALOG_EDIT_COMPONENT_IN_LIBRARY::LAST_LAYOUT
     DIALOG_EDIT_COMPONENT_IN_LIBRARY::m_lastLayout = DIALOG_EDIT_COMPONENT_IN_LIBRARY::NONE;
@@ -70,8 +70,6 @@ DIALOG_EDIT_COMPONENT_IN_LIBRARY::DIALOG_EDIT_COMPONENT_IN_LIBRARY( LIB_EDIT_FRA
     m_delayedFocusPage( -1 ),
     m_width( 0 )
 {
-    m_config = Kiface().KifaceSettings();
-
     // Give a bit more room for combobox editors
     m_grid->SetDefaultRowSize( m_grid->GetDefaultRowSize() + 4 );
     m_fields = new FIELDS_GRID_TABLE<LIB_FIELD>( this, aParent, m_libEntry );
@@ -79,8 +77,8 @@ DIALOG_EDIT_COMPONENT_IN_LIBRARY::DIALOG_EDIT_COMPONENT_IN_LIBRARY( LIB_EDIT_FRA
     m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
 
     // Show/hide columns according to the user's preference
-    m_config->Read( LibEditFieldsShownColumnsKey, &m_shownColumns, wxT( "0 1 2 3 4 5 6 7" ) );
-    m_grid->ShowHideColumns( m_shownColumns );
+    auto cfg = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
+    m_grid->ShowHideColumns( cfg->m_EditComponentVisibleColumns );
 
     wxGridCellAttr* attr = new wxGridCellAttr;
     attr->SetEditor( new GRID_CELL_URL_EDITOR( this ) );
@@ -132,7 +130,8 @@ DIALOG_EDIT_COMPONENT_IN_LIBRARY::~DIALOG_EDIT_COMPONENT_IN_LIBRARY()
 {
     m_lastOpenedPage = m_NoteBook->GetSelection( );
 
-    m_config->Write( LibEditFieldsShownColumnsKey, m_grid->GetShownColumns() );
+    auto cfg = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
+    cfg->m_EditComponentVisibleColumns = m_grid->GetShownColumns();
 
     // Prevents crash bug in wxGrid's d'tor
     m_grid->DestroyTable( m_fields );
diff --git a/eeschema/dialogs/dialog_edit_component_in_lib.h b/eeschema/dialogs/dialog_edit_component_in_lib.h
index f8aec21eb6..d44eddaf77 100644
--- a/eeschema/dialogs/dialog_edit_component_in_lib.h
+++ b/eeschema/dialogs/dialog_edit_component_in_lib.h
@@ -48,8 +48,6 @@ class DIALOG_EDIT_COMPONENT_IN_LIBRARY: public DIALOG_EDIT_COMPONENT_IN_LIBRARY_
     static LAST_LAYOUT m_lastLayout;
 
 public:
-    wxConfigBase*   m_config;
-
     LIB_EDIT_FRAME* m_Parent;
     LIB_PART*       m_libEntry;
 
diff --git a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp
index 03f4bdde84..702164025b 100644
--- a/eeschema/dialogs/dialog_edit_component_in_schematic.cpp
+++ b/eeschema/dialogs/dialog_edit_component_in_schematic.cpp
@@ -34,6 +34,7 @@
 #include <widgets/wx_grid.h>
 
 #include <class_library.h>
+#include <eeschema_settings.h>
 #include <fields_grid_table.h>
 #include <invoke_sch_dialog.h>
 #include <sch_draw_panel.h>
@@ -48,15 +49,10 @@
 #endif /* KICAD_SPICE */
 
 
-#define SymbolFieldsShownColumnsKey   wxT( "SymbolFieldsShownColumns" )
-
-
 DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( SCH_EDIT_FRAME* aParent,
                                                                         SCH_COMPONENT* aComponent ) :
     DIALOG_EDIT_COMPONENT_IN_SCHEMATIC_BASE( aParent )
 {
-    m_config = Kiface().KifaceSettings();
-
     m_cmp = aComponent;
     m_part = m_cmp->GetPartRef().get();
     m_fields = new FIELDS_GRID_TABLE<SCH_FIELD>( this, aParent, m_part );
@@ -84,7 +80,8 @@ DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( SCH_EDIT
     m_grid->PushEventHandler( new FIELDS_GRID_TRICKS( m_grid, this ) );
 
     // Show/hide columns according to user's preference
-    m_config->Read( SymbolFieldsShownColumnsKey, &m_shownColumns, wxT( "0 1 2 3 4 5 6 7" ) );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+    m_shownColumns = cfg->m_Appearance.edit_component_visible_columns;
     m_grid->ShowHideColumns( m_shownColumns );
 
     wxToolTip::Enable( true );
@@ -108,7 +105,8 @@ DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::DIALOG_EDIT_COMPONENT_IN_SCHEMATIC( SCH_EDIT
 
 DIALOG_EDIT_COMPONENT_IN_SCHEMATIC::~DIALOG_EDIT_COMPONENT_IN_SCHEMATIC()
 {
-    m_config->Write( SymbolFieldsShownColumnsKey, m_grid->GetShownColumns() );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+    cfg->m_Appearance.edit_component_visible_columns = m_grid->GetShownColumns();
 
     // Prevents crash bug in wxGrid's d'tor
     m_grid->DestroyTable( m_fields );
diff --git a/eeschema/dialogs/dialog_edit_component_in_schematic.h b/eeschema/dialogs/dialog_edit_component_in_schematic.h
index 26d001a083..152bede53a 100644
--- a/eeschema/dialogs/dialog_edit_component_in_schematic.h
+++ b/eeschema/dialogs/dialog_edit_component_in_schematic.h
@@ -49,8 +49,6 @@ public:
     SCH_EDIT_FRAME* GetParent();
 
 private:
-    wxConfigBase* m_config;
-
     SCH_COMPONENT* m_cmp;
     LIB_PART*      m_part;
 
diff --git a/eeschema/dialogs/dialog_fields_editor_global.cpp b/eeschema/dialogs/dialog_fields_editor_global.cpp
index 0a65e2bece..0ca0bcae48 100644
--- a/eeschema/dialogs/dialog_fields_editor_global.cpp
+++ b/eeschema/dialogs/dialog_fields_editor_global.cpp
@@ -23,23 +23,24 @@
  */
 
 
-#include <wx/msgdlg.h>
-#include <wx/grid.h>
-#include <widgets/wx_grid.h>
 #include <base_units.h>
-#include <confirm.h>
 #include <bitmaps.h>
+#include <class_library.h>
+#include <confirm.h>
+#include <eda_doc.h>
+#include <eeschema_settings.h>
+#include <general.h>
 #include <grid_tricks.h>
 #include <kicad_string.h>
+#include <kiface_i.h>
 #include <refdes_utils.h>
-#include <general.h>
-#include <class_library.h>
 #include <sch_edit_frame.h>
 #include <sch_reference_list.h>
 #include <tools/sch_editor_control.h>
-#include <kiface_i.h>
-#include <eda_doc.h>
 #include <widgets/grid_text_button_helpers.h>
+#include <widgets/wx_grid.h>
+#include <wx/grid.h>
+#include <wx/msgdlg.h>
 
 #include "dialog_fields_editor_global.h"
 
@@ -666,7 +667,6 @@ public:
 
 DIALOG_FIELDS_EDITOR_GLOBAL::DIALOG_FIELDS_EDITOR_GLOBAL( SCH_EDIT_FRAME* parent ) :
         DIALOG_FIELDS_EDITOR_GLOBAL_BASE( parent ),
-        m_config( Kiface().KifaceSettings() ),
         m_parent( parent )
 {
     wxSize defaultDlgSize = ConvertDialogToPixels( wxSize( 600, 300 ) );
@@ -884,12 +884,31 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::AddField( const wxString& aName,
 
     wxVector<wxVariant> fieldsCtrlRow;
 
-    m_config->Read( "SymbolFieldEditor/Show/" + aName, &defaultShow );
-    m_config->Read( "SymbolFieldEditor/GroupBy/" + aName, &defaultSortBy );
+    auto cfg     = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+    bool show    = defaultShow;
+    bool sort_by = defaultSortBy;
+
+    std::string key( aName.ToUTF8() );
+
+    try
+    {
+        show = cfg->m_FieldEditorPanel.fields_show.at( key );
+    }
+    catch( std::out_of_range& )
+    {
+    }
+
+    try
+    {
+        show = cfg->m_FieldEditorPanel.fields_group_by.at( key );
+    }
+    catch( std::out_of_range& )
+    {
+    }
 
     fieldsCtrlRow.push_back( wxVariant( aName ) );
-    fieldsCtrlRow.push_back( wxVariant( defaultShow ) );
-    fieldsCtrlRow.push_back( wxVariant( defaultSortBy ) );
+    fieldsCtrlRow.push_back( wxVariant( show ) );
+    fieldsCtrlRow.push_back( wxVariant( sort_by ) );
 
     m_fieldsCtrl->AppendItem( fieldsCtrlRow );
 }
@@ -912,7 +931,8 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::LoadFieldNames()
     }
 
     // Force References to always be shown
-    m_config->Write( "SymbolFieldEditor/Show/Reference", true );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+    cfg->m_FieldEditorPanel.fields_show["Reference"] = true;
 
     // *DO NOT* use translated mandatory field names:
     // They are also used as keyword to find fields in component list.
@@ -964,7 +984,10 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::OnAddField( wxCommandEvent& event )
         }
     }
 
-    m_config->Write( "SymbolFieldEditor/Show/" + fieldName, true );
+    std::string key( fieldName.ToUTF8() );
+
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+    cfg->m_FieldEditorPanel.fields_show[key] = true;
 
     AddField( fieldName, true, false );
 
@@ -983,6 +1006,7 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::OnAddField( wxCommandEvent& event )
 
 void DIALOG_FIELDS_EDITOR_GLOBAL::OnColumnItemToggled( wxDataViewEvent& event )
 {
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
     wxDataViewItem item = event.GetItem();
 
     int row = m_fieldsCtrl->ItemToRow( item );
@@ -1005,8 +1029,8 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::OnColumnItemToggled( wxDataViewEvent& event )
             m_fieldsCtrl->SetToggleValue( value, row, col );
         }
 
-        wxString fieldName = m_fieldsCtrl->GetTextValue( row, FIELD_NAME_COLUMN );
-        m_config->Write( "SymbolFieldEditor/Show/" + fieldName, value );
+        std::string fieldName( m_fieldsCtrl->GetTextValue( row, FIELD_NAME_COLUMN ).ToUTF8() );
+        cfg->m_FieldEditorPanel.fields_show[fieldName] = value;
 
         if( value )
             m_grid->ShowCol( row );
@@ -1018,8 +1042,9 @@ void DIALOG_FIELDS_EDITOR_GLOBAL::OnColumnItemToggled( wxDataViewEvent& event )
     case GROUP_BY_COLUMN:
     {
         bool value = m_fieldsCtrl->GetToggleValue( row, col );
-        wxString fieldName = m_fieldsCtrl->GetTextValue( row, FIELD_NAME_COLUMN );
-        m_config->Write( "SymbolFieldEditor/GroupBy/" + fieldName, value );
+        std::string fieldName( m_fieldsCtrl->GetTextValue( row, FIELD_NAME_COLUMN ).ToUTF8() );
+        cfg->m_FieldEditorPanel.fields_group_by[fieldName] = value;
+
         m_dataModel->RebuildRows( m_groupComponentsBox, m_fieldsCtrl );
         m_dataModel->Sort( m_grid->GetSortingColumn(), m_grid->IsSortOrderAscending() );
         m_grid->ForceRefresh();
diff --git a/eeschema/dialogs/dialog_fields_editor_global.h b/eeschema/dialogs/dialog_fields_editor_global.h
index ec09959feb..55075e7dce 100644
--- a/eeschema/dialogs/dialog_fields_editor_global.h
+++ b/eeschema/dialogs/dialog_fields_editor_global.h
@@ -44,7 +44,6 @@ public:
     bool TransferDataFromWindow() override;
 
 private:
-    wxConfigBase*                  m_config;
     SCH_EDIT_FRAME*                m_parent;
     int                            m_showColWidth;
     int                            m_groupByColWidth;
diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp
index 5b357cc201..79e561af37 100644
--- a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp
+++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp
@@ -21,20 +21,20 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <connection_graph.h>
+#include <dialog_global_edit_text_and_graphics_base.h>
 #include <fctsys.h>
 #include <kicad_string.h>
-#include <widgets/unit_binder.h>
+#include <sch_component.h>
+#include <sch_connection.h>
+#include <sch_edit_frame.h>
+#include <sch_line.h>
+#include <sch_sheet.h>
+#include <advanced_config.h>
 #include <tool/tool_manager.h>
 #include <tools/ee_selection_tool.h>
 #include <tools/sch_edit_tool.h>
-#include <sch_edit_frame.h>
-#include <sch_component.h>
-#include <sch_line.h>
-#include <sch_connection.h>
-#include <sch_sheet.h>
-#include <connection_graph.h>
-#include <dialog_global_edit_text_and_graphics_base.h>
-#include <advanced_config.h>
+#include <widgets/unit_binder.h>
 
 static bool       g_modifyReferences;
 static bool       g_modifyValues;
diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
index c1bd0576cc..bd34f06f2a 100644
--- a/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
+++ b/eeschema/dialogs/dialog_lib_edit_pin_table.cpp
@@ -22,21 +22,20 @@
  */
 
 #include "dialog_lib_edit_pin_table.h"
+#include "grid_tricks.h"
 #include "lib_pin.h"
 #include "pin_number.h"
-#include "grid_tricks.h"
-#include <widgets/grid_icon_text_helpers.h>
-#include <widgets/wx_grid.h>
-#include <queue>
 #include <base_units.h>
 #include <bitmaps.h>
-#include <wx/bmpcbox.h>
-#include <kiface_i.h>
-#include <kicad_string.h>
 #include <confirm.h>
+#include <kicad_string.h>
+#include <kiface_i.h>
 #include <lib_edit_frame.h>
-
-#define PinTableShownColumnsKey    wxT( "PinTableShownColumns" )
+#include <libedit_settings.h>
+#include <queue>
+#include <widgets/grid_icon_text_helpers.h>
+#include <widgets/wx_grid.h>
+#include <wx/bmpcbox.h>
 
 
 static std::vector<BITMAP_DEF> g_typeIcons;
@@ -393,8 +392,6 @@ DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( LIB_EDIT_FRAME* parent, LI
     m_editFrame( parent ),
     m_part( aPart )
 {
-    m_config = Kiface().KifaceSettings();
-
     if( g_typeNames.empty())
     {
         for( unsigned i = 0; i < ELECTRICAL_PINTYPES_TOTAL; ++i )
@@ -428,7 +425,9 @@ DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( LIB_EDIT_FRAME* parent, LI
     m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
 
     // Show/hide columns according to the user's preference
-    m_config->Read( PinTableShownColumnsKey, &m_columnsShown, wxT( "0 1 2 3 4 8 9" ) );
+    auto cfg = parent->GetSettings();
+    m_columnsShown = cfg->m_PinTableVisibleColumns;
+
     m_grid->ShowHideColumns( m_columnsShown );
 
     // Set special attributes
@@ -480,7 +479,8 @@ DIALOG_LIB_EDIT_PIN_TABLE::DIALOG_LIB_EDIT_PIN_TABLE( LIB_EDIT_FRAME* parent, LI
 
 DIALOG_LIB_EDIT_PIN_TABLE::~DIALOG_LIB_EDIT_PIN_TABLE()
 {
-    m_config->Write( PinTableShownColumnsKey, m_grid->GetShownColumns() );
+    auto cfg = m_editFrame->GetSettings();
+    cfg->m_PinTableVisibleColumns = m_grid->GetShownColumns().ToStdString();
 
     // Disconnect Events
     m_grid->Disconnect( wxEVT_GRID_COL_SORT, wxGridEventHandler( DIALOG_LIB_EDIT_PIN_TABLE::OnColSort ), nullptr, this );
diff --git a/eeschema/dialogs/dialog_lib_edit_pin_table.h b/eeschema/dialogs/dialog_lib_edit_pin_table.h
index 2508e79951..f6e4c82365 100644
--- a/eeschema/dialogs/dialog_lib_edit_pin_table.h
+++ b/eeschema/dialogs/dialog_lib_edit_pin_table.h
@@ -72,7 +72,6 @@ protected:
     void adjustGridColumns( int aWidth );
 
     LIB_EDIT_FRAME*       m_editFrame;
-    wxConfigBase*         m_config;
     bool                  m_initialized = false;
     int                   m_originalColWidths[ COL_COUNT ];
     wxString              m_columnsShown;
diff --git a/eeschema/dialogs/dialog_netlist.cpp b/eeschema/dialogs/dialog_netlist.cpp
index c69e060d7c..984c43574a 100644
--- a/eeschema/dialogs/dialog_netlist.cpp
+++ b/eeschema/dialogs/dialog_netlist.cpp
@@ -44,6 +44,7 @@
 #include <wildcards_and_files_ext.h>
 #include <invoke_sch_dialog.h>
 #include <netlist_exporters/netlist_exporter_pspice.h>
+#include <eeschema_settings.h>
 
 #include <eeschema_id.h>
 #include <wx/regex.h>
@@ -113,7 +114,6 @@ public:
 
 protected:
     bool                 m_asFormatSelected;
-    wxConfigBase*        m_config;
 
 public:
     // Constructor and destructor
@@ -153,16 +153,6 @@ private:
      */
     void WriteCurrentNetlistSetup();
 
-    /**
-     * Function UserNetlistTypeName
-     * to retrieve user netlist type names
-     * @param first_item = true: return first name of the list, false = return next
-     * @return a wxString : name of the type netlist or empty string
-     * this function must be called first with "first_item" = true
-     * and after with "first_item" = false to get all the other existing netlist names
-     */
-    const wxString UserNetlistTypeName( bool first_item );
-
     /**
      * Function FilenamePrms
      * returns the filename extension and the wildcard string for this curr
@@ -213,13 +203,6 @@ enum id_netlist {
 };
 
 
-// keywords for configuration:
-#define CUSTOM_NETLIST_TITLE   wxT( "CustomNetlistTitle" )
-#define CUSTOM_NETLIST_COMMAND wxT( "CustomNetlistCommand" )
-#define NETLIST_USE_DEFAULT_NETNAME wxT( "NetlistUseDefaultNetname" )
-#define NETLIST_PSPICE_USE_NETNAME  wxT( "SpiceUseNetNames" )
-
-
 BEGIN_EVENT_TABLE( NETLIST_DIALOG, NETLIST_DIALOG_BASE )
     EVT_CHECKBOX( ID_CURRENT_FORMAT_IS_DEFAULT, NETLIST_DIALOG::SelectDefaultNetlistType )
 END_EVENT_TABLE()
@@ -275,10 +258,7 @@ NETLIST_DIALOG::NETLIST_DIALOG( SCH_EDIT_FRAME* parent ) :
     NETLIST_DIALOG_BASE( parent )
 {
     m_Parent = parent;
-    m_config = Kiface().KifaceSettings();
 
-    long tmp;
-    m_config->Read( NETLIST_USE_DEFAULT_NETNAME, &tmp, 0l );
     m_DefaultNetFmtName = m_Parent->GetNetListFormatName();
 
     for( NETLIST_PAGE_DIALOG*& page : m_PanelNetType)
@@ -323,22 +303,6 @@ NETLIST_DIALOG::NETLIST_DIALOG( SCH_EDIT_FRAME* parent ) :
 }
 
 
-const wxString NETLIST_DIALOG::UserNetlistTypeName( bool first_item )
-{
-    static int index;
-
-    if( first_item )
-        index = 0;
-    else
-        index++;
-
-    wxString msg = CUSTOM_NETLIST_TITLE;
-    msg << index + 1;
-
-    return m_config->Read( msg );
-}
-
-
 void NETLIST_DIALOG::InstallPageSpice()
 {
     NETLIST_PAGE_DIALOG* page = m_PanelNetType[PANELSPICE] =
@@ -354,24 +318,25 @@ void NETLIST_DIALOG::InstallPageSpice()
 
 void NETLIST_DIALOG::InstallCustomPages()
 {
-    int                  ii;
-    wxString             title;
     NETLIST_PAGE_DIALOG* currPage;
 
-    for( ii = 0; ii < CUSTOMPANEL_COUNTMAX; ii++ )
-    {
-        title = UserNetlistTypeName( ii == 0 ? true : false );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
 
-        if( title.IsEmpty() )
+    for( size_t i = 0;
+         i < CUSTOMPANEL_COUNTMAX && i < cfg->m_NetlistPanel.custom_command_titles.size(); i++ )
+    {
+        // pairs of (title, command) are stored
+        wxString title = cfg->m_NetlistPanel.custom_command_titles[i];
+
+        if( i >= cfg->m_NetlistPanel.custom_command_paths.size() )
             break; // No more panel to install
 
-        // Install a plugin panel
-        wxString msg = CUSTOM_NETLIST_COMMAND;
-        msg << ii + 1;
-        wxString command = m_config->Read( msg );
+        wxString command = cfg->m_NetlistPanel.custom_command_paths[i];
 
-        currPage = AddOneCustomPage( title, command, (NETLIST_TYPE_ID)(NET_TYPE_CUSTOM1 + ii) );
-        m_PanelNetType[PANELCUSTOMBASE + ii] = currPage;
+        currPage = AddOneCustomPage( title, command,
+                static_cast<NETLIST_TYPE_ID>( NET_TYPE_CUSTOM1 + i ) );
+
+        m_PanelNetType[PANELCUSTOMBASE + i] = currPage;
     }
 }
 
@@ -585,8 +550,12 @@ void NETLIST_DIALOG::WriteCurrentNetlistSetup()
 
     NetlistUpdateOpt();
 
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+
+    cfg->m_NetlistPanel.custom_command_titles.clear();
+    cfg->m_NetlistPanel.custom_command_paths.clear();
+
     // Update existing custom pages
-    int jj = 0;
     for( int ii = 0; ii < CUSTOMPANEL_COUNTMAX; ii++ )
     {
         NETLIST_PAGE_DIALOG* currPage = m_PanelNetType[ii + PANELCUSTOMBASE];
@@ -599,27 +568,9 @@ void NETLIST_DIALOG::WriteCurrentNetlistSetup()
         if( title.IsEmpty() )
             continue;
 
-        msg = CUSTOM_NETLIST_TITLE;
-        msg << jj + 1;
-        m_config->Write( msg, title );
-
-        wxString Command = currPage->m_CommandStringCtrl->GetValue();
-        msg = CUSTOM_NETLIST_COMMAND;
-        msg << jj + 1;
-        m_config->Write( msg, Command );
-        jj++;
-    }
-
-    // Ensure all other pages are void
-    for( ; jj < CUSTOMPANEL_COUNTMAX; jj++ )
-    {
-        msg = CUSTOM_NETLIST_TITLE;
-        msg << jj + 1;
-        m_config->Write( msg, wxEmptyString );
-
-        msg = CUSTOM_NETLIST_COMMAND;
-        msg << jj + 1;
-        m_config->Write( msg, wxEmptyString );
+        cfg->m_NetlistPanel.custom_command_titles.push_back( title.ToStdString() );
+        cfg->m_NetlistPanel.custom_command_paths.push_back(
+                currPage->m_CommandStringCtrl->GetValue().ToStdString() );
     }
 }
 
diff --git a/eeschema/dialogs/dialog_plot_schematic.cpp b/eeschema/dialogs/dialog_plot_schematic.cpp
index 353641ebb0..5ba2d11042 100644
--- a/eeschema/dialogs/dialog_plot_schematic.cpp
+++ b/eeschema/dialogs/dialog_plot_schematic.cpp
@@ -28,21 +28,13 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <pgm_base.h>
-#include <kiface_i.h>
 #include <bitmaps.h>
-#include <ws_painter.h>
-#include <sch_sheet.h>
 #include <dialog_plot_schematic.h>
-
-
-// Keys for configuration
-#define PLOT_FORMAT_KEY wxT( "PlotFormat" )
-#define PLOT_MODECOLOR_KEY wxT( "PlotModeColor" )
-#define PLOT_FRAME_REFERENCE_KEY wxT( "PlotFrameRef" )
-#define PLOT_HPGL_ORIGIN_KEY wxT( "PlotHPGLOrg" )
-#define PLOT_HPGL_PAPERSIZE_KEY wxT( "PlotHPGLPaperSize" )
-#define PLOT_HPGL_PEN_SIZE_KEY wxT( "PlotHPGLPenSize" )
+#include <eeschema_settings.h>
+#include <kiface_i.h>
+#include <pgm_base.h>
+#include <sch_sheet.h>
+#include <ws_painter.h>
 
 
 // static members (static to remember last state):
@@ -69,7 +61,6 @@ DIALOG_PLOT_SCHEMATIC::DIALOG_PLOT_SCHEMATIC( SCH_EDIT_FRAME* parent )
           m_defaultLineWidth( parent, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits, true ),
           m_penWidth( parent, m_penWidthLabel, m_penWidthCtrl, m_penWidthUnits, true )
 {
-    m_config = Kiface().KifaceSettings();
     m_configChanged = false;
 
     m_browseButton->SetBitmap( KiBitmap( folder_xpm ) );
@@ -92,30 +83,24 @@ DIALOG_PLOT_SCHEMATIC::DIALOG_PLOT_SCHEMATIC( SCH_EDIT_FRAME* parent )
 // Initialize the dialog options:
 void DIALOG_PLOT_SCHEMATIC::initDlg()
 {
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+
     // Set color or B&W plot option
-    bool tmp;
-    m_config->Read( PLOT_MODECOLOR_KEY, &tmp, true );
-    setModeColor( tmp );
+    setModeColor( cfg->m_PlotPanel.color );
 
     // Set plot or not frame reference option
-    m_config->Read( PLOT_FRAME_REFERENCE_KEY, &tmp, true );
-    setPlotFrameRef( tmp );
+    setPlotFrameRef( cfg->m_PlotPanel.frame_reference );
 
     // Set HPGL plot origin to center of paper of left bottom corner
-    m_config->Read( PLOT_HPGL_ORIGIN_KEY, &tmp, false );
-    SetPlotOriginCenter( tmp );
+    SetPlotOriginCenter( cfg->m_PlotPanel.hpgl_origin );
 
-    m_config->Read( PLOT_HPGL_PAPERSIZE_KEY, &m_HPGLPaperSizeSelect, 0 );
+    m_HPGLPaperSizeSelect = cfg->m_PlotPanel.hpgl_paper_size;
 
     // HPGL Pen Size is stored in mm in config
-    m_config->Read( PLOT_HPGL_PEN_SIZE_KEY, &m_HPGLPenSize, 0.5 );
-    m_HPGLPenSize *= IU_PER_MM;
+    m_HPGLPenSize = cfg->m_PlotPanel.hpgl_pen_size * IU_PER_MM;
 
     // Switch to the last save plot format
-    int plotfmt;
-    m_config->Read( PLOT_FORMAT_KEY, &plotfmt, 0 );
-
-    switch( static_cast<PLOT_FORMAT>( plotfmt ) )
+    switch( static_cast<PLOT_FORMAT>( cfg->m_PlotPanel.format ) )
     {
     default:
     case PLOT_FORMAT::POST:
@@ -270,14 +255,16 @@ void DIALOG_PLOT_SCHEMATIC::getPlotOptions()
 {
     m_HPGLPenSize = m_penWidth.GetValue();
 
-    m_config->Write( PLOT_MODECOLOR_KEY, getModeColor() );
-    m_config->Write( PLOT_FRAME_REFERENCE_KEY, getPlotFrameRef() );
-    m_config->Write( PLOT_FORMAT_KEY, (long) GetPlotFileFormat() );
-    m_config->Write( PLOT_HPGL_ORIGIN_KEY, GetPlotOriginCenter() );
-    m_config->Write( PLOT_HPGL_PAPERSIZE_KEY, m_HPGLPaperSizeSelect );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+
+    cfg->m_PlotPanel.color = getModeColor();
+    cfg->m_PlotPanel.frame_reference = getPlotFrameRef();
+    cfg->m_PlotPanel.format = static_cast<int>( GetPlotFileFormat() );
+    cfg->m_PlotPanel.hpgl_origin = GetPlotOriginCenter();
+    cfg->m_PlotPanel.hpgl_paper_size = m_HPGLPaperSizeSelect;
 
     // HPGL Pen Size is stored in mm in config
-    m_config->Write( PLOT_HPGL_PEN_SIZE_KEY, m_HPGLPenSize/IU_PER_MM );
+    cfg->m_PlotPanel.hpgl_pen_size = m_HPGLPenSize / IU_PER_MM;
 
     SetDefaultLineThickness( m_defaultLineWidth.GetValue() );
 
diff --git a/eeschema/dialogs/dialog_plot_schematic.h b/eeschema/dialogs/dialog_plot_schematic.h
index 82b9e7d588..648dec941a 100644
--- a/eeschema/dialogs/dialog_plot_schematic.h
+++ b/eeschema/dialogs/dialog_plot_schematic.h
@@ -47,7 +47,6 @@ class DIALOG_PLOT_SCHEMATIC : public DIALOG_PLOT_SCHEMATIC_BASE
 {
 private:
     SCH_EDIT_FRAME* m_parent;
-    wxConfigBase*   m_config;
     bool            m_configChanged; // true if a project config param has changed
     PLOT_FORMAT     m_plotFormat;
     static int      m_pageSizeSelect;       // Static to keep last option for some format
diff --git a/eeschema/dialogs/dialog_print_using_printer.cpp b/eeschema/dialogs/dialog_print_using_printer.cpp
index 80330b39c1..45bc571073 100644
--- a/eeschema/dialogs/dialog_print_using_printer.cpp
+++ b/eeschema/dialogs/dialog_print_using_printer.cpp
@@ -443,7 +443,7 @@ void SCH_PRINTOUT::PrintPage( SCH_SCREEN* aScreen )
     {
         m_parent->PrintWorkSheet( dc, aScreen, GetDefaultLineThickness(), IU_PER_MILS,
                                   aScreen->GetFileName(), wxEmptyString,
-                                  GetLayerColor( ( SCH_LAYER_ID )LAYER_WORKSHEET ) );
+                                  m_parent->GetLayerColor( LAYER_SCHEMATIC_WORKSHEET ) );
     }
 
     aScreen->Print( dc );
diff --git a/eeschema/dialogs/dialog_rescue_each.cpp b/eeschema/dialogs/dialog_rescue_each.cpp
index 04c83289e5..1918aa6177 100644
--- a/eeschema/dialogs/dialog_rescue_each.cpp
+++ b/eeschema/dialogs/dialog_rescue_each.cpp
@@ -21,19 +21,19 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <sch_edit_frame.h>
-#include <sch_component.h>
-#include <invoke_sch_dialog.h>
-#include <dialog_rescue_each_base.h>
-#include <kiface_i.h>
-#include <class_library.h>
-#include <class_libentry.h>
-#include <set>
-#include <vector>
-#include <project_rescue.h>
-#include <eeschema_config.h>
-#include <symbol_preview_widget.h>
 #include <class_draw_panel_gal.h>
+#include <class_libentry.h>
+#include <class_library.h>
+#include <dialog_rescue_each_base.h>
+#include <eeschema_settings.h>
+#include <invoke_sch_dialog.h>
+#include <kiface_i.h>
+#include <project_rescue.h>
+#include <sch_component.h>
+#include <sch_edit_frame.h>
+#include <set>
+#include <symbol_preview_widget.h>
+#include <vector>
 
 
 class DIALOG_RESCUE_EACH: public DIALOG_RESCUE_EACH_BASE
@@ -58,7 +58,6 @@ public:
 private:
     SYMBOL_PREVIEW_WIDGET* m_previewNewWidget;
     SYMBOL_PREVIEW_WIDGET* m_previewOldWidget;
-    wxConfigBase*   m_Config;
     RESCUER*        m_Rescuer;
     SCH_SHEET_PATH* m_currentSheet;
     bool            m_AskShowAgain;
@@ -95,7 +94,6 @@ DIALOG_RESCUE_EACH::DIALOG_RESCUE_EACH( wxWindow* aParent,
     m_previewNewWidget = new SYMBOL_PREVIEW_WIDGET( m_previewNewPanel,  Kiway(), aGalBackEndType );
 	m_SizerNewPanel->Add( m_previewNewWidget, 1, wxEXPAND | wxALL, 5 );
 
-    m_Config = Kiface().KifaceSettings();
     m_stdButtonsOK->SetDefault();
 
     // Set the info message, customized to include the proper suffix.
@@ -294,7 +292,8 @@ void DIALOG_RESCUE_EACH::OnNeverShowClick( wxCommandEvent& aEvent )
 
     if( resp == wxID_YES )
     {
-        m_Config->Write( RescueNeverShowEntry, true );
+        auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
+        cfg->m_RescueNeverShow = true;
         m_Rescuer->m_chosen_candidates.clear();
         Close();
     }
diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp
index 32529c7560..7ba44632b7 100644
--- a/eeschema/eeschema.cpp
+++ b/eeschema/eeschema.cpp
@@ -29,6 +29,7 @@
 #include <confirm.h>
 #include <gestfich.h>
 #include <eda_dde.h>
+#include <eeschema_settings.h>
 #include <sch_edit_frame.h>
 #include <lib_edit_frame.h>
 #include <lib_view_frame.h>
@@ -40,6 +41,7 @@
 #include <dialogs/panel_sym_lib_table.h>
 #include <kiway.h>
 #include <sim/sim_plot_frame.h>
+#include <settings/settings_manager.h>
 #include <sexpr/sexpr.h>
 #include <sexpr/sexpr_parser.h>
 
@@ -162,6 +164,7 @@ PGM_BASE& Pgm()
 }
 
 
+// TODO(JE) Get rid of this on a second pass through eeschema
 static COLOR4D s_layerColor[LAYER_ID_COUNT];
 
 COLOR4D GetLayerColor( SCH_LAYER_ID aLayer )
@@ -171,70 +174,13 @@ COLOR4D GetLayerColor( SCH_LAYER_ID aLayer )
     return s_layerColor[layer];
 }
 
-void SetLayerColor( COLOR4D aColor, SCH_LAYER_ID aLayer )
+
+void OnColorsChanged()
 {
-    // Do not allow non-background layers to be completely white.
-    // This ensures the BW printing recognizes that the colors should be printed black.
-    if( aColor == COLOR4D::WHITE && aLayer != LAYER_SCHEMATIC_BACKGROUND )
-        aColor.Darken( 0.01 );
+    COLOR_SETTINGS* cs = Pgm().GetSettingsManager().GetColorSettings();
 
-    unsigned layer = aLayer;
-    wxASSERT( layer < arrayDim( s_layerColor ) );
-    s_layerColor[layer] = aColor;
-}
-
-
-static std::vector<PARAM_CFG*>& cfg_params()
-{
-    static std::vector<PARAM_CFG*> ca;
-
-    if( !ca.size() )
-    {
-        // These are KIFACE specific, they need to be loaded once when the
-        // eeschema KIFACE comes in.
-
-#define CLR(x, y, z)\
-    ca.push_back( new PARAM_CFG_SETCOLOR( true, wxT( x ),\
-                                          &s_layerColor[( y )], z ) );
-
-        CLR( "Color4DWireEx",             LAYER_WIRE,                 COLOR4D( GREEN ) )
-        CLR( "Color4DBusEx",              LAYER_BUS,                  COLOR4D( BLUE ) )
-        CLR( "Color4DConnEx",             LAYER_JUNCTION,             COLOR4D( GREEN ) )
-        CLR( "Color4DLLabelEx",           LAYER_LOCLABEL,             COLOR4D( BLACK ) )
-        CLR( "Color4DHLabelEx",           LAYER_HIERLABEL,            COLOR4D( BROWN ) )
-        CLR( "Color4DGLabelEx",           LAYER_GLOBLABEL,            COLOR4D( RED ) )
-        CLR( "Color4DPinNumEx",           LAYER_PINNUM,               COLOR4D( RED ) )
-        CLR( "Color4DPinNameEx",          LAYER_PINNAM,               COLOR4D( CYAN ) )
-        CLR( "Color4DFieldEx",            LAYER_FIELDS,               COLOR4D( MAGENTA ) )
-        CLR( "Color4DReferenceEx",        LAYER_REFERENCEPART,        COLOR4D( CYAN ) )
-        CLR( "Color4DValueEx",            LAYER_VALUEPART,            COLOR4D( CYAN ) )
-        CLR( "Color4DNoteEx",             LAYER_NOTES,                COLOR4D( LIGHTBLUE ) )
-        CLR( "Color4DBodyEx",             LAYER_DEVICE,               COLOR4D( RED ) )
-        CLR( "Color4DBodyBgEx",           LAYER_DEVICE_BACKGROUND,    COLOR4D( LIGHTYELLOW ) )
-        CLR( "Color4DNetNameEx",          LAYER_NETNAM,               COLOR4D( DARKGRAY ) )
-        CLR( "Color4DPinEx",              LAYER_PIN,                  COLOR4D( RED ) )
-        CLR( "Color4DSheetEx",            LAYER_SHEET,                COLOR4D( MAGENTA ) )
-        CLR( "Color4DSheetFileNameEx",    LAYER_SHEETFILENAME,        COLOR4D( BROWN ) )
-        CLR( "Color4DSheetNameEx",        LAYER_SHEETNAME,            COLOR4D( CYAN ) )
-        CLR( "Color4DSheetLabelEx",       LAYER_SHEETLABEL,           COLOR4D( BROWN ) )
-        CLR( "Color4DNoConnectEx",        LAYER_NOCONNECT,            COLOR4D( BLUE ) )
-        CLR( "Color4DErcWEx",             LAYER_ERC_WARN,             COLOR4D( GREEN ).WithAlpha(0.8 ) )
-        CLR( "Color4DErcEEx",             LAYER_ERC_ERR,              COLOR4D( RED ).WithAlpha(0.8 ) )
-        CLR( "Color4DGridEx",             LAYER_SCHEMATIC_GRID,       COLOR4D( DARKGRAY ) )
-        CLR( "Color4DBgCanvasEx",         LAYER_SCHEMATIC_BACKGROUND, COLOR4D( WHITE ) )
-        CLR( "Color4DCursorEx",           LAYER_SCHEMATIC_CURSOR,     COLOR4D( BLACK ) )
-        CLR( "Color4DBrightenedEx",       LAYER_BRIGHTENED,           COLOR4D( PUREMAGENTA ) )
-        CLR( "Color4DHiddenEx",           LAYER_HIDDEN,               COLOR4D( LIGHTGRAY ) )
-        CLR( "Color4DWorksheetEx",        LAYER_WORKSHEET,            COLOR4D( RED ) )
-// Macs look better with a lighter shadow
-#ifdef __WXMAC__
-        CLR( "Color4DShadowEx",           LAYER_SELECTION_SHADOWS,    COLOR4D( .78, .92, 1.0, 0.8 ) )
-#else
-        CLR( "Color4DShadowEx",           LAYER_SELECTION_SHADOWS,    COLOR4D( .4, .7, 1.0, 0.8 ) )
-#endif
-    }
-
-    return ca;
+    for( SCH_LAYER_ID layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; ++layer )
+        s_layerColor[layer] = cs->GetColor( layer );
 }
 
 
@@ -242,17 +188,12 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
 {
     // This is process-level-initialization, not project-level-initialization of the DSO.
     // Do nothing in here pertinent to a project!
+    InitSettings( new EESCHEMA_SETTINGS );
+    aProgram->GetSettingsManager().RegisterSettings( KifaceSettings() );
 
     start_common( aCtlBits );
 
-    // Give a default colour for all layers (actual color will be initialized by config)
-    for( SCH_LAYER_ID ii = SCH_LAYER_ID_START; ii < SCH_LAYER_ID_END; ++ii )
-        SetLayerColor( COLOR4D( DARKGRAY ), ii );
-
-    SetLayerColor( COLOR4D::WHITE, LAYER_SCHEMATIC_BACKGROUND );
-    SetLayerColor( COLOR4D::BLACK, LAYER_SCHEMATIC_CURSOR );
-
-    wxConfigLoadSetups( KifaceSettings(), cfg_params() );
+    OnColorsChanged();
 
     wxFileName fn = SYMBOL_LIB_TABLE::GetGlobalTableFileName();
 
@@ -292,7 +233,13 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
 
 void IFACE::OnKifaceEnd()
 {
-    wxConfigSaveSetups( KifaceSettings(), cfg_params() );
+    COLOR_SETTINGS* cs = Pgm().GetSettingsManager().GetColorSettings();
+
+    for( SCH_LAYER_ID layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; ++layer )
+    {
+        cs->SetColor( layer, GetLayerColor( layer ) );
+    }
+
     end_common();
 }
 
diff --git a/eeschema/eeschema_config.cpp b/eeschema/eeschema_config.cpp
index 096ab26054..48a9aff7cd 100644
--- a/eeschema/eeschema_config.cpp
+++ b/eeschema/eeschema_config.cpp
@@ -21,31 +21,33 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <pgm_base.h>
-#include <kiface_i.h>
-#include <confirm.h>
-#include <gestfich.h>
-#include <sch_edit_frame.h>
-#include <sch_sheet.h>
-#include <lib_edit_frame.h>
-#include <eeschema_config.h>
-#include <ws_data_model.h>
 #include <class_library.h>
-#include <symbol_lib_table.h>
-#include <wildcards_and_files_ext.h>
-#include <widgets/paged_dialog.h>
-#include <dialogs/panel_eeschema_template_fieldnames.h>
-#include <dialogs/panel_eeschema_settings.h>
+#include <confirm.h>
 #include <dialogs/panel_eeschema_display_options.h>
+#include <dialogs/panel_eeschema_settings.h>
+#include <dialogs/panel_eeschema_template_fieldnames.h>
+#include <dialogs/panel_libedit_settings.h>
+#include <eeschema_config.h>
+#include <eeschema_settings.h>
+#include <fctsys.h>
+#include <gestfich.h>
+#include <gr_text.h>
+#include <kiface_i.h>
+#include <lib_edit_frame.h>
 #include <panel_display_options.h>
 #include <panel_hotkeys_editor.h>
-#include <widgets/widget_eeschema_color_config.h>
-#include <widgets/symbol_tree_pane.h>
-#include <dialogs/panel_libedit_settings.h>
+#include <pgm_base.h>
+#include <sch_edit_frame.h>
+#include <sch_junction.h>
 #include <sch_painter.h>
-#include <gr_text.h>
-#include "sch_junction.h"
+#include <sch_sheet.h>
+#include <settings/app_settings.h>
+#include <symbol_lib_table.h>
+#include <widgets/paged_dialog.h>
+#include <widgets/symbol_tree_pane.h>
+#include <widgets/widget_eeschema_color_config.h>
+#include <wildcards_and_files_ext.h>
+#include <ws_data_model.h>
 
 static int s_defaultBusThickness = Mils2iu( DEFAULTBUSTHICKNESS );
 static int s_defaultWireThickness  = Mils2iu( DEFAULTDRAWLINETHICKNESS );
@@ -293,134 +295,46 @@ void SCH_EDIT_FRAME::SaveProjectSettings( bool aAskForSave )
     SetDefaultTextSize( Mils2iu( GetDefaultTextSize() ) );
 }
 
-///@{
-/// \ingroup config
 
-const wxChar RescueNeverShowEntry[] =               wxT( "RescueNeverShow" );
-const wxChar AutoplaceFieldsEntry[] =               wxT( "AutoplaceFields" );
-const wxChar AutoplaceJustifyEntry[] =              wxT( "AutoplaceJustify" );
-const wxChar AutoplaceAlignEntry[] =                wxT( "AutoplaceAlign" );
-static const wxChar DragActionIsMoveEntry[] =       wxT( "DragActionIsMove" );
-static const wxChar FootprintPreviewEntry[] =       wxT( "FootprintPreview" );
-static const wxChar NavigatorStaysOpenEntry[] =     wxT( "NavigatorStaysOpen" );
-static const wxChar DefaultBusWidthEntry[] =        wxT( "DefaultBusWidth" );
-static const wxChar DefaultWireWidthEntry[] =       wxT( "DefaultWireWidth" );
-static const wxChar DefaultDrawLineWidthEntry[] =   wxT( "DefaultDrawLineWidth" );
-static const wxChar DefaultJctSizeEntry[] =         wxT( "DefaultJunctionSize" );
-static const wxChar ShowHiddenPinsEntry[] =         wxT( "ShowHiddenPins" );
-static const wxChar HorzVertLinesOnlyEntry[] =      wxT( "HorizVertLinesOnly" );
-static const wxChar FieldNamesEntry[] =             wxT( "FieldNames" );
-static const wxString TextMarkupFlagsEntry =        "TextMarkupFlags";
-static const wxString ShowPageLimitsEntry =         "ShowPageLimits";
-static const wxString UnitsEntry =                  "Units";
-static const wxString PrintMonochromeEntry =        "PrintMonochrome";
-static const wxString PrintSheetRefEntry =          "PrintSheetReferenceAndTitleBlock";
-static const wxString RepeatStepXEntry =            "RepeatStepX";
-static const wxString RepeatStepYEntry =            "RepeatStepY";
-static const wxString RepeatLabelIncrementEntry =   "RepeatLabelIncrement";
-static const wxString ShowIllegalSymboLibDialog =   "ShowIllegalSymbolLibDialog";
-static const wxString showSheetFileNameCaseSensitivityDlg = "ShowSheetFileNameCaseSensitivityDlg";
-static const wxString SelectPinSelectSymbolEntry =  "SelectPinSelectSymbolOpt";
-
-// Library editor wxConfig entry names.
-static const wxChar defaultLibWidthEntry[] =        wxT( "LibeditLibWidth" );
-static const wxChar defaultPinNumSizeEntry[] =      wxT( "LibeditPinNumSize" );
-static const wxChar defaultPinNameSizeEntry[] =     wxT( "LibeditPinNameSize" );
-static const wxChar DefaultPinLengthEntry[] =       wxT( "DefaultPinLength" );
-static const wxChar repeatLibLabelIncEntry[] =      wxT( "LibeditRepeatLabelInc" );
-static const wxChar pinRepeatStepEntry[] =          wxT( "LibeditPinRepeatStep" );
-static const wxChar repeatLibStepXEntry[] =         wxT( "LibeditRepeatStepX" );
-static const wxChar repeatLibStepYEntry[] =         wxT( "LibeditRepeatStepY" );
-static const wxChar showPinElectricalType[] =       wxT( "LibeditShowPinElectricalType" );
-
-static const wxChar boxedSelectedText[] =           wxT( "SelectionTextAsBox" );
-static const wxChar drawSelectedChildren[] =        wxT( "SelectionDrawChildItems" );
-static const wxChar selectionFillShapes[] =         wxT( "SelectionFillShapes" );
-static const wxChar selectionThickness[] =          wxT( "SelectionThickness" );
-
-///@}
-
-std::vector<PARAM_CFG*>& SCH_EDIT_FRAME::GetConfigurationSettings()
-{
-    if( !m_configSettings.empty() )
-        return m_configSettings;
-
-    m_configSettings.push_back( new PARAM_CFG_BOOL( true, ShowPageLimitsEntry,
-                                                    &m_showPageLimits, true ) );
-    m_configSettings.push_back( new PARAM_CFG_INT( true, UnitsEntry,
-                                                   (int*) &m_userUnits,
-                                                   (int) EDA_UNITS::MILLIMETRES ) );
-
-    m_configSettings.push_back( new PARAM_CFG_BOOL( true, PrintMonochromeEntry,
-                                                    &m_printMonochrome, true ) );
-    m_configSettings.push_back( new PARAM_CFG_BOOL( true, PrintSheetRefEntry,
-                                                    &m_printSheetReference, true ) );
-
-    m_configSettings.push_back( new PARAM_CFG_INT( true, RepeatLabelIncrementEntry,
-                                                   &m_repeatDeltaLabel, DEFAULT_REPEAT_LABEL_INC,
-                                                   -10, +10 ) );
-    m_configSettings.push_back( new PARAM_CFG_BOOL( true, ShowIllegalSymboLibDialog,
-                                                    &m_showIllegalSymbolLibDialog, true ) );
-    m_configSettings.push_back( new PARAM_CFG_BOOL( true, showSheetFileNameCaseSensitivityDlg,
-                                                    &m_showSheetFileNameCaseSensitivityDlg,
-                                                    true ) );
-
-    return m_configSettings;
-}
-
-
-void SCH_EDIT_FRAME::LoadSettings( wxConfigBase* aCfg )
+void SCH_EDIT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_DRAW_FRAME::LoadSettings( aCfg );
 
-    long tmp;
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
 
-    wxConfigLoadSetups( aCfg, GetConfigurationSettings() );
-
-    aCfg->Read( RepeatStepXEntry, &tmp, DEFAULT_REPEAT_OFFSET_X );
-    m_repeatStep.x = Mils2iu( static_cast< int >( tmp ) );
-    aCfg->Read( RepeatStepYEntry, &tmp, DEFAULT_REPEAT_OFFSET_Y );
-    m_repeatStep.y = Mils2iu( static_cast< int >( tmp ) );
+    m_repeatStep.x = Mils2iu( cfg->m_Drawing.default_repeat_offset_x );
+    m_repeatStep.y = Mils2iu( cfg->m_Drawing.default_repeat_offset_y );
 
     // LibEdit owns this one, but we must read it in if LibEdit hasn't set it yet
     if( GetDefaultLineThickness() < 0 )
-    {
-        SetDefaultLineThickness( Mils2iu( (int) aCfg->Read( DefaultDrawLineWidthEntry,
-                                                            DEFAULTDRAWLINETHICKNESS ) ) );
-    }
+        SetDefaultLineThickness( Mils2iu( cfg->m_Drawing.default_line_thickness ) );
 
-    SetDefaultBusThickness( Mils2iu( (int) aCfg->Read( DefaultBusWidthEntry,
-                                                       DEFAULTBUSTHICKNESS ) ) );
+    SetDefaultBusThickness( Mils2iu( cfg->m_Drawing.default_bus_thickness ) );
 
     // Property introduced in 6.0; use DefaultLineWidth for earlier projects
-    if( !aCfg->Read( DefaultWireWidthEntry, &tmp ) )
-        aCfg->Read( DefaultDrawLineWidthEntry, &tmp, DEFAULTDRAWLINETHICKNESS );
+    SetDefaultWireThickness( Mils2iu( cfg->m_Drawing.default_wire_thickness) );
 
-    SetDefaultWireThickness( Mils2iu( (int) tmp ) );
+    SetSelectionTextAsBox( cfg->m_Selection.text_as_box );
+    SetSelectionDrawChildItems( cfg->m_Selection.draw_selected_children );
+    SetSelectionFillShapes( cfg->m_Selection.fill_shapes );
+    SetSelectionThickness( Mils2iu( cfg->m_Selection.thickness ) );
 
-    SetSelectionTextAsBox( aCfg->ReadBool( boxedSelectedText, false ) );
-    SetSelectionDrawChildItems( aCfg->ReadBool( drawSelectedChildren, true ) );
-    SetSelectionFillShapes( aCfg->ReadBool( selectionFillShapes, false ) );
-    SetSelectionThickness(
-        Mils2iu( static_cast<int>( aCfg->Read( selectionThickness,
-                                       DEFAULTSELECTIONTHICKNESS ) ) ) );
+    SetTextMarkupFlags( cfg->m_Drawing.text_markup_flags );
 
-    SetTextMarkupFlags( (int) aCfg->Read( TextMarkupFlagsEntry, 0L ) );
+    SCH_JUNCTION::SetSymbolSize( Mils2iu( cfg->m_Drawing.default_junction_size ) );
 
-    if( aCfg->Read( DefaultJctSizeEntry, &tmp ) )
-        SCH_JUNCTION::SetSymbolSize( Mils2iu( (int) tmp ) );
+    m_footprintPreview      = cfg->m_Appearance.footprint_preview;
+    m_navigatorStaysOpen    = cfg->m_Appearance.navigator_stays_open;
+    m_showAllPins           = cfg->m_Appearance.show_hidden_pins;
+    m_autoplaceFields       = cfg->m_AutoplaceFields.enable;
+    m_autoplaceAlign        = cfg->m_AutoplaceFields.align_to_grid;
+    m_autoplaceJustify      = cfg->m_AutoplaceFields.allow_rejustify;
+    m_forceHVLines          = cfg->m_Drawing.hv_lines_only;
+    m_dragActionIsMove      = cfg->m_Input.drag_is_move;
+    m_selectPinSelectSymbol = cfg->m_Selection.select_pin_selects_symbol;
+    m_repeatDeltaLabel      = cfg->m_Drawing.repeat_label_increment;
 
-    aCfg->Read( DragActionIsMoveEntry, &m_dragActionIsMove, true );
-    aCfg->Read( ShowHiddenPinsEntry, &m_showAllPins, false );
-    aCfg->Read( SelectPinSelectSymbolEntry, &m_selectPinSelectSymbol, true );
-    aCfg->Read( HorzVertLinesOnlyEntry, &m_forceHVLines, true );
-    aCfg->Read( AutoplaceFieldsEntry, &m_autoplaceFields, true );
-    aCfg->Read( AutoplaceJustifyEntry, &m_autoplaceJustify, true );
-    aCfg->Read( AutoplaceAlignEntry, &m_autoplaceAlign, false );
-    aCfg->Read( FootprintPreviewEntry, &m_footprintPreview, false );
-    aCfg->Read( NavigatorStaysOpenEntry, &m_navigatorStaysOpen, false );
-
-    wxString templateFieldNames = aCfg->Read( FieldNamesEntry, wxEmptyString );
+    wxString templateFieldNames = cfg->m_Drawing.field_names;
 
     if( !templateFieldNames.IsEmpty() )
     {
@@ -446,30 +360,49 @@ void SCH_EDIT_FRAME::LoadSettings( wxConfigBase* aCfg )
 }
 
 
-void SCH_EDIT_FRAME::SaveSettings( wxConfigBase* aCfg )
+void SCH_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_DRAW_FRAME::SaveSettings( aCfg );
 
-    wxConfigSaveSetups( aCfg, GetConfigurationSettings() );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
 
-    aCfg->Write( RepeatStepXEntry, static_cast< long >( Iu2Mils( m_repeatStep.x ) ) );
-    aCfg->Write( RepeatStepYEntry, static_cast< long >( Iu2Mils( m_repeatStep.y ) ) );
-    aCfg->Write( DragActionIsMoveEntry, m_dragActionIsMove );
-    aCfg->Write( DefaultBusWidthEntry, (long) Iu2Mils( GetDefaultBusThickness() ) );
-    aCfg->Write( DefaultWireWidthEntry, (long) Iu2Mils( GetDefaultWireThickness() ) );
-    aCfg->Write( DefaultJctSizeEntry, (long) Iu2Mils( SCH_JUNCTION::GetSymbolSize() ) );
-    aCfg->Write( ShowHiddenPinsEntry, m_showAllPins );
-    aCfg->Write( SelectPinSelectSymbolEntry, GetSelectPinSelectSymbol() );
-    aCfg->Write( HorzVertLinesOnlyEntry, GetForceHVLines() );
-    aCfg->Write( AutoplaceFieldsEntry, m_autoplaceFields );
-    aCfg->Write( AutoplaceJustifyEntry, m_autoplaceJustify );
-    aCfg->Write( AutoplaceAlignEntry, m_autoplaceAlign );
-    aCfg->Write( FootprintPreviewEntry, m_footprintPreview );
-    aCfg->Write( boxedSelectedText, GetSelectionTextAsBox() );
-    aCfg->Write( drawSelectedChildren, GetSelectionDrawChildItems() );
-    aCfg->Write( selectionFillShapes, GetSelectionFillShapes() );
-    aCfg->Write( selectionThickness, Iu2Mils( GetSelectionThickness() ) );
-    aCfg->Write( NavigatorStaysOpenEntry, m_navigatorStaysOpen );
+    // TODO(JE) do most of these need to live as class members here, or can the sites that need
+    // the setting just grab a pointer to the EESCHEMA_SETTINGS and look them up directly?
+
+    cfg->m_Appearance.footprint_preview         = m_footprintPreview;
+    cfg->m_Appearance.navigator_stays_open      = m_navigatorStaysOpen;
+    cfg->m_Appearance.print_sheet_reference     = m_printSheetReference;
+    cfg->m_Appearance.show_hidden_pins          = m_showAllPins;
+    cfg->m_Appearance.show_illegal_symbol_lib_dialog = m_showIllegalSymbolLibDialog;
+    cfg->m_Appearance.show_page_limits          = m_showPageLimits;
+    cfg->m_Appearance.show_sheet_filename_case_sensitivity_dialog =
+            m_showSheetFileNameCaseSensitivityDlg;
+
+    cfg->m_AutoplaceFields.enable               = m_autoplaceFields;
+    cfg->m_AutoplaceFields.allow_rejustify      = m_autoplaceJustify;
+    cfg->m_AutoplaceFields.align_to_grid        = m_autoplaceAlign;
+
+    cfg->m_Drawing.default_bus_thickness        = Iu2Mils( GetDefaultBusThickness() );
+    cfg->m_Drawing.default_line_thickness       = Iu2Mils( GetDefaultLineThickness() );
+    cfg->m_Drawing.default_junction_size        = Iu2Mils( SCH_JUNCTION::GetSymbolSize() );
+    cfg->m_Drawing.default_repeat_offset_x      = Iu2Mils( m_repeatStep.x );
+    cfg->m_Drawing.default_repeat_offset_y      = Iu2Mils( m_repeatStep.y );
+    cfg->m_Drawing.default_wire_thickness       = Iu2Mils( GetDefaultWireThickness() );
+    cfg->m_Drawing.hv_lines_only                = GetForceHVLines();
+    cfg->m_Drawing.repeat_label_increment       = m_repeatDeltaLabel;
+    cfg->m_Drawing.text_markup_flags            = GetTextMarkupFlags();
+
+    cfg->m_Input.drag_is_move                   = m_dragActionIsMove;
+
+    cfg->m_Printing.monochrome                  = m_printMonochrome;
+
+    cfg->m_Selection.thickness                  = Iu2Mils( GetSelectionThickness() );
+    cfg->m_Selection.draw_selected_children     = GetSelectionDrawChildItems();
+    cfg->m_Selection.fill_shapes                = GetSelectionFillShapes();
+    cfg->m_Selection.select_pin_selects_symbol  = GetSelectPinSelectSymbol();
+    cfg->m_Selection.text_as_box                = GetSelectionTextAsBox();
+
+    cfg->m_System.units                         = static_cast<int>( m_userUnits );
 
     // Save template fieldnames
     STRING_FORMATTER sf;
@@ -479,80 +412,7 @@ void SCH_EDIT_FRAME::SaveSettings( wxConfigBase* aCfg )
     record.Replace( wxT("\n"), wxT(""), true );   // strip all newlines
     record.Replace( wxT("  "), wxT(" "), true );  // double space to single
 
-    aCfg->Write( FieldNamesEntry, record );
-
-    aCfg->Write( TextMarkupFlagsEntry, GetTextMarkupFlags() );
-    aCfg->Write( showSheetFileNameCaseSensitivityDlg, m_showSheetFileNameCaseSensitivityDlg );
-}
-
-
-void LIB_EDIT_FRAME::LoadSettings( wxConfigBase* aCfg )
-{
-    EDA_DRAW_FRAME::LoadSettings( aCfg );
-
-    SetDefaultLineThickness( Mils2iu( (int) aCfg->Read( DefaultDrawLineWidthEntry,
-                                                        DEFAULTDRAWLINETHICKNESS ) ) );
-    SetDefaultPinLength( Mils2iu( (int) aCfg->Read( DefaultPinLengthEntry, DEFAULTPINLENGTH ) ) );
-    m_textPinNumDefaultSize = Mils2iu( (int) aCfg->Read( defaultPinNumSizeEntry,
-                                                         DEFAULTPINNUMSIZE ) );
-    m_textPinNameDefaultSize = Mils2iu( (int) aCfg->Read( defaultPinNameSizeEntry,
-                                                          DEFAULTPINNAMESIZE ) );
-    SetRepeatDeltaLabel( (int) aCfg->Read( repeatLibLabelIncEntry, DEFAULT_REPEAT_LABEL_INC ) );
-    SetRepeatPinStep( Mils2iu( (int) aCfg->Read( pinRepeatStepEntry,
-                                                 DEFAULT_REPEAT_OFFSET_PIN ) ) );
-
-    wxPoint step;
-    step.x = Mils2iu( static_cast< int >( aCfg->Read( repeatLibStepXEntry,
-            static_cast< long >( DEFAULT_REPEAT_OFFSET_X ) ) ) );
-    step.y = Mils2iu( static_cast< int >( aCfg->Read( repeatLibStepYEntry,
-            static_cast< long >( DEFAULT_REPEAT_OFFSET_Y ) ) ) );
-
-    SetRepeatStep( step );
-    m_showPinElectricalTypeName = aCfg->ReadBool( showPinElectricalType, true );
-    aCfg->Read( defaultLibWidthEntry, &m_defaultLibWidth, DEFAULTLIBWIDTH );
-
-    wxString templateFieldNames = aCfg->Read( FieldNamesEntry, wxEmptyString );
-
-    if( !templateFieldNames.IsEmpty() )
-    {
-        TEMPLATE_FIELDNAMES_LEXER  lexer( TO_UTF8( templateFieldNames ) );
-
-        try
-        {
-            m_templateFieldNames.Parse( &lexer );
-        }
-        catch( const IO_ERROR& DBG( e ) )
-        {
-            // @todo show error msg
-            DBG( printf( "templatefieldnames parsing error: '%s'\n", TO_UTF8( e.What() ) ); )
-        }
-    }
-
-    auto painter = static_cast<KIGFX::SCH_PAINTER*>( GetCanvas()->GetView()->GetPainter() );
-    KIGFX::SCH_RENDER_SETTINGS* settings = painter->GetSettings();
-    settings->m_ShowPinsElectricalType = m_showPinElectricalTypeName;
-
-    // Hidden elements must be editable
-    settings->m_ShowHiddenText = true;
-    settings->m_ShowHiddenPins = true;
-    settings->m_ShowUmbilicals = false;
-}
-
-
-void LIB_EDIT_FRAME::SaveSettings( wxConfigBase* aCfg )
-{
-    EDA_DRAW_FRAME::SaveSettings( aCfg );
-
-    aCfg->Write( DefaultDrawLineWidthEntry, Iu2Mils( GetDefaultLineThickness() ) );
-    aCfg->Write( DefaultPinLengthEntry, Iu2Mils( GetDefaultPinLength() ) );
-    aCfg->Write( defaultPinNumSizeEntry, Iu2Mils( GetPinNumDefaultSize() ) );
-    aCfg->Write( defaultPinNameSizeEntry, Iu2Mils( GetPinNameDefaultSize() ) );
-    aCfg->Write( repeatLibLabelIncEntry, GetRepeatDeltaLabel() );
-    aCfg->Write( pinRepeatStepEntry, Iu2Mils( GetRepeatPinStep() ) );
-    aCfg->Write( repeatLibStepXEntry, Iu2Mils( GetRepeatStep().x ) );
-    aCfg->Write( repeatLibStepYEntry, Iu2Mils( GetRepeatStep().y ) );
-    aCfg->Write( showPinElectricalType, GetShowElectricalType() );
-    aCfg->Write( defaultLibWidthEntry, m_treePane->GetSize().x );
+    cfg->m_Drawing.field_names = record.ToStdString();
 }
 
 
diff --git a/eeschema/eeschema_settings.cpp b/eeschema/eeschema_settings.cpp
new file mode 100644
index 0000000000..a78fd756e8
--- /dev/null
+++ b/eeschema/eeschema_settings.cpp
@@ -0,0 +1,500 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#include <eeschema_settings.h>
+#include <layers_id_colors_and_visibility.h>
+#include <libedit_settings.h>
+#include <pgm_base.h>
+#include <settings/common_settings.h>
+#include <settings/parameters.h>
+#include <settings/settings_manager.h>
+#include <wx/config.h>
+
+
+///! Update the schema version whenever a migration is required
+const int eeschemaSchemaVersion = 0;
+
+
+EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() : APP_SETTINGS_BASE( "eeschema", eeschemaSchemaVersion )
+{
+    m_params.emplace_back( new PARAM<wxString>( "appearance.edit_component_visible_columns",
+            &m_Appearance.edit_component_visible_columns, "0 1 2 3 4 5 6 7" ) );
+
+    m_params.emplace_back( new PARAM<bool>( "appearance.footprint_preview",
+            &m_Appearance.footprint_preview, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "appearance.navigator_stays_open",
+            &m_Appearance.navigator_stays_open, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "appearance.print_sheet_reference",
+            &m_Appearance.print_sheet_reference, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "appearance.show_hidden_pins",
+            &m_Appearance.show_hidden_pins, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "appearance.show_illegal_symbol_lib_dialog",
+            &m_Appearance.show_illegal_symbol_lib_dialog, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "appearance.show_page_limits",
+            &m_Appearance.show_page_limits, true ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "appearance.show_sheet_filename_case_sensitivity_dialog",
+            &m_Appearance.show_sheet_filename_case_sensitivity_dialog, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "autoplace_fields.enable",
+            &m_AutoplaceFields.enable, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "autoplace_fields.allow_rejustify",
+            &m_AutoplaceFields.allow_rejustify, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "autoplace_fields.align_to_grid",
+            &m_AutoplaceFields.align_to_grid, true ) );
+
+    m_params.emplace_back( new PARAM<int>( "drawing.default_bus_thickness",
+            &m_Drawing.default_bus_thickness, 12 ) );
+
+    m_params.emplace_back( new PARAM<int>( "drawing.default_junction_size",
+            &m_Drawing.default_junction_size, 40 ) );
+
+    m_params.emplace_back( new PARAM<int>( "drawing.default_line_thickness",
+            &m_Drawing.default_line_thickness, 6 ) );
+
+    m_params.emplace_back( new PARAM<int>( "drawing.default_repeat_offset_x",
+            &m_Drawing.default_repeat_offset_x, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "drawing.default_repeat_offset_y",
+            &m_Drawing.default_repeat_offset_y, 100 ) );
+
+    m_params.emplace_back( new PARAM<int>( "drawing.default_wire_thickness",
+            &m_Drawing.default_wire_thickness, 6 ) );
+
+    m_params.emplace_back(
+            new PARAM<wxString>( "drawing.field_names", &m_Drawing.field_names, "" ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "drawing.hv_lines_only", &m_Drawing.hv_lines_only, true ) );
+
+    m_params.emplace_back( new PARAM<int>( "drawing.repeat_label_increment",
+            &m_Drawing.repeat_label_increment, 1, -10, 10 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "drawing.text_markup_flags", &m_Drawing.text_markup_flags, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "input.drag_is_move", &m_Input.drag_is_move, true ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "selection.thickness", &m_Selection.thickness, 3 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "selection.draw_selected_children",
+            &m_Selection.draw_selected_children, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "selection.fill_shapes",
+            &m_Selection.fill_shapes, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "selection.select_pin_selects_symbol",
+            &m_Selection.select_pin_selects_symbol, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "selection.text_as_box",
+            &m_Selection.text_as_box, false ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "annotation.method", &m_AnnotatePanel.method, 0, 0, 2 ) );
+
+    m_params.emplace_back( new PARAM<int>( "annotation.messages_filter",
+            &m_AnnotatePanel.messages_filter, -1 ) );
+
+    m_params.emplace_back( new PARAM<int>( "annotation.sort_order",
+            &m_AnnotatePanel.sort_order, 0, 0, 1 ) );
+
+    m_params.emplace_back(
+            new PARAM<wxString>( "bom.selected_plugin", &m_BomPanel.selected_plugin, "" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "bom.plugins", &m_BomPanel.plugins, "" ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_revision",
+            &m_PageSettings.export_revision, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_date",
+            &m_PageSettings.export_date, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_title",
+            &m_PageSettings.export_title, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_company",
+            &m_PageSettings.export_company, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_comment1",
+            &m_PageSettings.export_comment1, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_comment2",
+            &m_PageSettings.export_comment2, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_comment3",
+            &m_PageSettings.export_comment3, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_comment4",
+            &m_PageSettings.export_comment4, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_comment5",
+            &m_PageSettings.export_comment5, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_comment6",
+            &m_PageSettings.export_comment6, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_comment7",
+            &m_PageSettings.export_comment7, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_comment8",
+            &m_PageSettings.export_comment8, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "page_settings.export_comment9",
+            &m_PageSettings.export_comment9, false ) );
+
+    m_params.emplace_back( new PARAM_MAP<bool>( "field_editor.fields_show",
+            &m_FieldEditorPanel.fields_show, {} ) );
+
+    m_params.emplace_back( new PARAM_MAP<bool>( "field_editor.fields_group_by",
+            &m_FieldEditorPanel.fields_group_by, {} ) );
+
+    m_params.emplace_back( new PARAM<bool>( "plot.color", &m_PlotPanel.color, true ) );
+
+    m_params.emplace_back( new PARAM<int>( "plot.format", &m_PlotPanel.format, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "plot.frame_reference",
+            &m_PlotPanel.frame_reference, true ) );
+
+    m_params.emplace_back( new PARAM<int>( "plot.hpgl_paper_size",
+            &m_PlotPanel.hpgl_paper_size, 0 ) );
+
+    m_params.emplace_back( new PARAM<double>( "plot.hpgl_pen_size",
+            &m_PlotPanel.hpgl_pen_size, 0.5 ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "plot.hpgl_origin", &m_PlotPanel.hpgl_origin, false ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "simulator.window.pos_x", &m_Simulator.window.pos_x, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "simulator.window.pos_y", &m_Simulator.window.pos_y, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "simulator.window.size_x",
+            &m_Simulator.window.size_x, 500 ) );
+
+    m_params.emplace_back( new PARAM<int>( "simulator.window.size_y",
+            &m_Simulator.window.size_y, 400 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "simulator.window.maximized",
+            &m_Simulator.window.maximized, false ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "simulator.window.perspective",
+            &m_Simulator.window.perspective, "" ) );
+
+    m_params.emplace_back( new PARAM<int>( "simulator.plot_panel_width",
+            &m_Simulator.plot_panel_width, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "simulator.plot_panel_height",
+            &m_Simulator.plot_panel_height, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "simulator.signal_panel_height",
+            &m_Simulator.signal_panel_height, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "simulator.cursors_panel_height",
+            &m_Simulator.cursors_panel_height, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "simulator.white_background",
+            &m_Simulator.white_background, false ) );
+
+    m_params.emplace_back( new PARAM<int>( "symbol_chooser.sash_pos_h",
+            &m_SymChooserPanel.sash_pos_h, -1 ) );
+
+    m_params.emplace_back( new PARAM<int>( "symbol_chooser.sash_pos_v",
+            &m_SymChooserPanel.sash_pos_v, -1 ) );
+
+    m_params.emplace_back( new PARAM<int>( "symbol_chooser.width",
+            &m_SymChooserPanel.width, -1 ) );
+
+    m_params.emplace_back( new PARAM<int>( "symbol_chooser.height",
+            &m_SymChooserPanel.height, -1 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "symbol_chooser.keep_symbol",
+            &m_SymChooserPanel.keep_symbol, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "symbol_chooser.place_all_units",
+            &m_SymChooserPanel.place_all_units, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "system.never_show_rescue_dialog",
+            &m_RescueNeverShow, false ) );
+
+    m_params.emplace_back( new PARAM<int>( "lib_view.window.pos_x",
+            &m_LibViewPanel.window.pos_x, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "lib_view.window.pos_y",
+            &m_LibViewPanel.window.pos_y, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "lib_view.window.size_x",
+            &m_LibViewPanel.window.size_x, 500 ) );
+
+    m_params.emplace_back( new PARAM<int>( "lib_view.window.size_y",
+            &m_LibViewPanel.window.size_y, 400 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "lib_view.window.maximized",
+            &m_LibViewPanel.window.maximized, false ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "lib_view.window.perspective",
+            &m_LibViewPanel.window.perspective, "" ) );
+
+    m_params.emplace_back( new PARAM<int>( "lib_view.lib_list_width",
+            &m_LibViewPanel.lib_list_width, 150 ) );
+
+    m_params.emplace_back( new PARAM<int>( "lib_view.cmp_list_width",
+            &m_LibViewPanel.cmp_list_width, 150 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "lib_view.show_pin_electrical_type",
+            &m_LibViewPanel.show_pin_electrical_type, true ) );
+}
+
+
+bool EESCHEMA_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacy<bool>( aCfg, "FootprintPreview",   "appearance.footprint_preview" );
+    ret &= fromLegacy<bool>( aCfg, "NavigatorStaysOpen", "appearance.navigator_stays_open" );
+    ret &= fromLegacy<bool>( aCfg, "PrintSheetReferenceAndTitleBlock",
+            "appearance.print_sheet_reference" );
+    ret &= fromLegacy<bool>( aCfg, "ShowHiddenPins",     "appearance.show_hidden_pins" );
+    ret &= fromLegacy<bool>( aCfg, "ShowIllegalSymbolLibDialog",
+            "appearance.show_illegal_symbol_lib_dialog" );
+    ret &= fromLegacy<bool>( aCfg, "ShowPageLimits",     "appearance.show_page_limits" );
+    ret &= fromLegacy<bool>( aCfg, "ShowSheetFileNameCaseSensitivityDlg",
+            "appearance.show_sheet_filename_case_sensitivity_dialog" );
+
+    ret &= fromLegacy<bool>( aCfg, "AutoplaceFields",     "autoplace_fields.enable" );
+    ret &= fromLegacy<bool>( aCfg, "AutoplaceJustify",    "autoplace_fields.allow_rejustify" );
+    ret &= fromLegacy<bool>( aCfg, "AutoplaceAlign",      "autoplace_fields.align_to_grid" );
+
+    ret &= fromLegacy<int>(  aCfg, "DefaultBusWidth",      "drawing.default_bus_thickness" );
+    ret &= fromLegacy<int>(  aCfg, "DefaultJunctionSize",  "drawing.default_junction_size" );
+    ret &= fromLegacy<int>(  aCfg, "DefaultDrawLineWidth", "drawing.default_line_thickness" );
+    ret &= fromLegacy<int>(  aCfg, "RepeatStepX",          "drawing.default_repeat_offset_x" );
+    ret &= fromLegacy<int>(  aCfg, "RepeatStepY",          "drawing.default_repeat_offset_y" );
+    ret &= fromLegacy<int>(  aCfg, "DefaultWireWidth",     "drawing.default_wire_thickness" );
+    ret &= fromLegacyString( aCfg, "FieldNames",           "drawing.field_names" );
+    ret &= fromLegacy<bool>( aCfg, "HorizVertLinesOnly",   "drawing.hv_lines_only" );
+    ret &= fromLegacy<int>(  aCfg, "RepeatLabelIncrement", "drawing.repeat_label_increment" );
+    ret &= fromLegacy<int>(  aCfg, "TextMarkupFlags",      "drawing.text_markup_flags" );
+
+    ret &= fromLegacy<bool>( aCfg, "DragActionIsMove",     "input.drag_is_move" );
+
+    ret &= fromLegacy<int>(  aCfg, "SelectionThickness",      "selection.thickness" );
+    ret &= fromLegacy<bool>( aCfg, "SelectionDrawChildItems", "selection.draw_selected_children" );
+    ret &= fromLegacy<bool>( aCfg, "SelectionFillShapes",     "selection.fill_shapes" );
+    ret &= fromLegacy<bool>( aCfg, "SelectPinSelectSymbolOpt",
+            "selection.select_pin_selects_symbol" );
+    ret &= fromLegacy<bool>( aCfg, "SelectionTextAsBox",      "selection.text_as_box" );
+
+    ret &= fromLegacy<int>(  aCfg, "AnnotateAlgoOption",      "annotation.method" );
+    ret &= fromLegacy<int>(  aCfg, "AnnotateFilterMsg",       "annotation.messages_filter" );
+    ret &= fromLegacy<int>(  aCfg, "AnnotateSortOption",      "annotation.sort_order" );
+
+    ret &= fromLegacyString( aCfg, "bom_plugin_selected",     "bom.selected_plugin" );
+    ret &= fromLegacyString( aCfg, "bom_plugins",             "bom.plugins" );
+
+    ret &= fromLegacyString( aCfg, "SymbolFieldsShownColumns",
+            "edit_sch_component.visible_columns" );
+
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportRevision", "page_settings.export_revision" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportDate",     "page_settings.export_date" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportTitle",    "page_settings.export_title" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportCompany",  "page_settings.export_company" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportComment1", "page_settings.export_comment1" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportComment2", "page_settings.export_comment2" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportComment3", "page_settings.export_comment3" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportComment4", "page_settings.export_comment4" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportComment5", "page_settings.export_comment5" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportComment6", "page_settings.export_comment6" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportComment7", "page_settings.export_comment7" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportComment8", "page_settings.export_comment8" );
+    ret &= fromLegacy<bool>( aCfg, "PageSettingsExportComment9", "page_settings.export_comment9" );
+
+    {
+        constexpr int max_custom_commands = 8;  // from DIALOG_NETLIST
+        nlohmann::json js_cmd   = nlohmann::json::array();
+        nlohmann::json js_title = nlohmann::json::array();
+        wxString cmd_key, title_key, cmd, title;
+
+        for( int i = 1; i <= max_custom_commands; ++i )
+        {
+            // Only migrate if both title and command are specified
+            cmd_key.Printf( "CustomNetlistCommand%d", i );
+            title_key.Printf( "CustomNetlistTitle%d", i );
+
+            if( aCfg->Read( cmd_key, &cmd ) && aCfg->Read( title_key, &title )
+                && !cmd.IsEmpty() && !title.IsEmpty() )
+            {
+                js_cmd.push_back( cmd.ToUTF8() );
+                js_title.push_back( title.ToUTF8() );
+            }
+        }
+
+        ( *this )[PointerFromString( "netlist.custom_command_titles" )] = js_title;
+        ( *this )[PointerFromString( "netlist.custom_command_paths" )]  = js_cmd;
+    }
+
+    {
+        // NOTE(JE) These parameters should move to project-local storage before V6, but we are
+        // migrating them here in order to preserve data.  There is a bug here that is preserved:
+        // keys are taken directly from the (translated) UI and stored in the config, so if the user
+        // changes languages the keys will no longer work.
+        aCfg->SetPath( "SymbolFieldEditor/Show/" );
+
+        nlohmann::json js = nlohmann::json( {} );
+        wxString key;
+        bool     value = false;
+        long     index = 0;
+
+        while( aCfg->GetNextEntry( key, index ) )
+        {
+            if( aCfg->Read( key, &value ) )
+            {
+                std::string key_utf( key.ToUTF8() );
+                js[PointerFromString( key_utf )] = value;
+            }
+        }
+
+        ( *this )[PointerFromString( "field_editor.fields_show" ) ] = js;
+
+        aCfg->SetPath( "../GroupBy" );
+
+        while( aCfg->GetNextEntry( key, index ) )
+        {
+            if( aCfg->Read( key, &value ) )
+            {
+                std::string key_utf( key.ToUTF8() );
+                js[PointerFromString( key_utf )] = value;
+            }
+        }
+
+        ( *this )[PointerFromString( "field_editor.fields_group_by" ) ] = js;
+
+        aCfg->SetPath( "../.." );
+    }
+
+    ret &= fromLegacy<bool>(   aCfg, "PlotModeColor",     "plot.color" );
+    ret &= fromLegacy<int>(    aCfg, "PlotFormat",        "plot.format" );
+    ret &= fromLegacy<bool>(   aCfg, "PlotFrameRef",      "plot.frame_reference" );
+    ret &= fromLegacy<bool>(   aCfg, "PlotHPGLOrg",       "plot.hpgl_origin" );
+    ret &= fromLegacy<int>(    aCfg, "PlotHPGLPaperSize", "plot.hpgl_paper_size" );
+    ret &= fromLegacy<double>( aCfg, "PlotHPGLPenSize",   "plot.hpgl_pen_size" );
+
+    ret &= fromLegacy<int>(    aCfg, "SIM_PLOT_FRAMEPos_x",       "simulator.window.pos_x" );
+    ret &= fromLegacy<int>(    aCfg, "SIM_PLOT_FRAMEPos_y",       "simulator.window.pos_y" );
+    ret &= fromLegacy<int>(    aCfg, "SIM_PLOT_FRAMESize_x",      "simulator.window.size_x" );
+    ret &= fromLegacy<int>(    aCfg, "SIM_PLOT_FRAMESize_y",      "simulator.window.size_y" );
+    ret &= fromLegacy<bool>(   aCfg, "SIM_PLOT_FRAMEMaximized",   "simulator.window.maximized" );
+    ret &= fromLegacyString(   aCfg, "SIM_PLOT_FRAMEPerspective", "simulator.window.perspective" );
+    ret &= fromLegacyString(   aCfg, "SIM_PLOT_FRAMEMostRecentlyUsedPath", "simulator.mru_path" );
+    ret &= fromLegacy<int>(    aCfg, "SimPlotPanelWidth",        "simulator.plot_panel_width" );
+    ret &= fromLegacy<int>(    aCfg, "SimPlotPanelHeight",       "simulator.plot_panel_height" );
+    ret &= fromLegacy<int>(    aCfg, "SimSignalPanelHeight",     "simulator.signal_panel_height" );
+    ret &= fromLegacy<int>(    aCfg, "SimCursorsPanelHeight",    "simulator.cursors_panel_height" );
+    ret &= fromLegacy<bool>(   aCfg, "SimPlotWhiteBg",           "simulator.white_background" );
+
+    ret &= fromLegacy<int>(  aCfg, "SymbolChooserHSashPosition", "symbol_chooser.sash_pos_h" );
+    ret &= fromLegacy<int>(  aCfg, "SymbolChooserVSashPosition", "symbol_chooser.sash_pos_v" );
+    ret &= fromLegacy<int>(  aCfg, "SymbolChooserWidth",         "symbol_chooser.width" );
+    ret &= fromLegacy<int>(  aCfg, "SymbolChooserHeight",        "symbol_chooser.height" );
+    ret &= fromLegacy<bool>( aCfg, "SymbolChooserKeepSymbol",    "symbol_chooser.keep_symbol" );
+    ret &= fromLegacy<bool>( aCfg, "SymbolChooserUseUnits",      "symbol_chooser.place_all_units" );
+
+    const std::string vlf = "ViewlibFrame";
+    ret &= fromLegacy<bool>( aCfg, vlf + "Maximized",            "lib_view.window.maximized" );
+    ret &= fromLegacyString( aCfg, vlf + "MostRecentlyUsedPath", "lib_view.window.mru_path" );
+    ret &= fromLegacy<int>(  aCfg, vlf + "Size_x",               "lib_view.window.size_x" );
+    ret &= fromLegacy<int>(  aCfg, vlf + "Size_y",               "lib_view.window.size_y" );
+    ret &= fromLegacyString( aCfg, vlf + "Perspective",          "lib_view.window.perspective" );
+    ret &= fromLegacy<int>(  aCfg, vlf + "Pos_x",                "lib_view.window.pos_x" );
+    ret &= fromLegacy<int>(  aCfg, vlf + "Pos_y",                "lib_view.window.pos_y" );
+    ret &= fromLegacy<int>(  aCfg, "ViewLiblistWidth",           "lib_view.lib_list_width" );
+    ret &= fromLegacy<int>(  aCfg, "ViewCmplistWidth",           "lib_view.cmp_list_width" );
+    ret &= fromLegacy<bool>( aCfg,
+            "ViewCmpShowPinElectricalType", "lib_view.show_pin_electrical_type" );
+    ret &= fromLegacy<bool>( aCfg, vlf + "ShowGrid",             "lib_view.grid.show" );
+    ret &= fromLegacy<int>(  aCfg, vlf + "_LastGridSize",        "lib_view.grid.last_size" );
+
+    ret &= fromLegacy<bool>( aCfg, "RescueNeverShow",     "system.never_show_rescue_dialog" );
+
+    // Legacy version stored this setting in eeschema, so move it to common if it exists
+    aCfg->Read( "MoveWarpsCursor", &Pgm().GetCommonSettings()->m_Input.warp_mouse_on_move );
+
+    COLOR_SETTINGS* cs = Pgm().GetSettingsManager().GetColorSettings();
+
+    auto migrateLegacyColor = [&] ( const std::string& aKey, int aLayerId ) {
+        wxString str;
+
+        if( aCfg->Read( aKey, &str ) )
+            cs->SetColor( aLayerId, COLOR4D( str ) );
+    };
+
+    migrateLegacyColor( "Color4DBgCanvasEx",        LAYER_SCHEMATIC_BACKGROUND );
+    migrateLegacyColor( "Color4DBodyBgEx",          LAYER_DEVICE_BACKGROUND );
+    migrateLegacyColor( "Color4DBodyEx",            LAYER_DEVICE );
+    migrateLegacyColor( "Color4DBrightenedEx",      LAYER_BRIGHTENED );
+    migrateLegacyColor( "Color4DBusEx",             LAYER_BUS );
+    migrateLegacyColor( "Color4DConnEx",            LAYER_JUNCTION );
+    migrateLegacyColor( "Color4DCursorEx",          LAYER_SCHEMATIC_CURSOR );
+    migrateLegacyColor( "Color4DErcEEx",            LAYER_ERC_ERR );
+    migrateLegacyColor( "Color4DErcWEx",            LAYER_ERC_WARN );
+    migrateLegacyColor( "Color4DFieldEx",           LAYER_FIELDS );
+    migrateLegacyColor( "Color4DGLabelEx",          LAYER_GLOBLABEL );
+    migrateLegacyColor( "Color4DGridEx",            LAYER_SCHEMATIC_GRID );
+    migrateLegacyColor( "Color4DHLabelEx",          LAYER_HIERLABEL );
+    migrateLegacyColor( "Color4DHiddenEx",          LAYER_HIDDEN );
+    migrateLegacyColor( "Color4DLLabelEx",          LAYER_LOCLABEL );
+    migrateLegacyColor( "Color4DNetNameEx",         LAYER_NETNAM );
+    migrateLegacyColor( "Color4DNoConnectEx",       LAYER_NOCONNECT );
+    migrateLegacyColor( "Color4DNoteEx",            LAYER_NOTES );
+    migrateLegacyColor( "Color4DPinEx",             LAYER_PIN );
+    migrateLegacyColor( "Color4DPinNameEx",         LAYER_PINNAM );
+    migrateLegacyColor( "Color4DPinNumEx",          LAYER_PINNUM );
+    migrateLegacyColor( "Color4DReferenceEx",       LAYER_REFERENCEPART );
+    migrateLegacyColor( "Color4DShadowEx",          LAYER_SELECTION_SHADOWS );
+    migrateLegacyColor( "Color4DSheetEx",           LAYER_SHEET );
+    migrateLegacyColor( "Color4DSheetFileNameEx",   LAYER_SHEETFILENAME );
+    migrateLegacyColor( "Color4DSheetLabelEx",      LAYER_SHEETLABEL );
+    migrateLegacyColor( "Color4DSheetNameEx",       LAYER_SHEETNAME );
+    migrateLegacyColor( "Color4DValueEx",           LAYER_VALUEPART );
+    migrateLegacyColor( "Color4DWireEx",            LAYER_WIRE );
+    migrateLegacyColor( "Color4DWorksheetEx",       LAYER_SCHEMATIC_WORKSHEET );
+
+    // LibEdit settings were stored with eeschema.  If eeschema is the first app to run,
+    // we need to migrate the LibEdit settings here
+
+    auto libedit = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>( false );
+    libedit->MigrateFromLegacy( aCfg );
+    libedit->Load();
+
+    return ret;
+}
\ No newline at end of file
diff --git a/eeschema/eeschema_settings.h b/eeschema/eeschema_settings.h
new file mode 100644
index 0000000000..e5c52eb1e1
--- /dev/null
+++ b/eeschema/eeschema_settings.h
@@ -0,0 +1,203 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#ifndef _EESCHEMA_SETTINGS_H
+#define _EESCHEMA_SETTINGS_H
+
+#include <settings/app_settings.h>
+
+
+class EESCHEMA_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+
+    struct APPEARANCE
+    {
+        wxString edit_component_visible_columns;
+        bool footprint_preview;
+        bool navigator_stays_open;
+        bool print_sheet_reference;
+        bool show_hidden_pins;
+        bool show_illegal_symbol_lib_dialog;
+        bool show_page_limits;
+        bool show_sheet_filename_case_sensitivity_dialog;
+    };
+
+    struct AUTOPLACE_FIELDS
+    {
+        bool enable;
+        bool allow_rejustify;
+        bool align_to_grid;
+    };
+
+    struct DRAWING
+    {
+        int default_bus_thickness;
+        int default_junction_size;
+        int default_line_thickness;
+        int default_repeat_offset_x;
+        int default_repeat_offset_y;
+        int default_wire_thickness;
+        wxString field_names;
+        bool hv_lines_only;
+        int repeat_label_increment;
+        int text_markup_flags;
+    };
+
+    struct INPUT
+    {
+        bool drag_is_move;
+    };
+
+    struct SELECTION
+    {
+        int  thickness;
+        bool draw_selected_children;
+        bool fill_shapes;
+        bool select_pin_selects_symbol;
+        bool text_as_box;
+    };
+
+    struct PAGE_SETTINGS
+    {
+        bool export_revision;
+        bool export_date;
+        bool export_title;
+        bool export_company;
+        bool export_comment1;
+        bool export_comment2;
+        bool export_comment3;
+        bool export_comment4;
+        bool export_comment5;
+        bool export_comment6;
+        bool export_comment7;
+        bool export_comment8;
+        bool export_comment9;
+    };
+
+    struct PANEL_ANNOTATE
+    {
+        int method;
+        int messages_filter;
+        int sort_order;
+    };
+
+    struct PANEL_BOM
+    {
+        wxString selected_plugin;
+        wxString plugins;
+    };
+
+    struct PANEL_FIELD_EDITOR
+    {
+        std::map<std::string, bool> fields_show;
+        std::map<std::string, bool> fields_group_by;
+    };
+
+    struct PANEL_LIB_VIEW
+    {
+        int lib_list_width;
+        int cmp_list_width;
+        bool show_pin_electrical_type;
+        WINDOW_SETTINGS window;
+    };
+
+    struct PANEL_NETLIST
+    {
+        std::vector<wxString> custom_command_titles;
+        std::vector<wxString> custom_command_paths;
+    };
+
+    struct PANEL_PLOT
+    {
+        bool   color;
+        int    format;
+        bool   frame_reference;
+        int    hpgl_paper_size;
+        double hpgl_pen_size;
+        bool   hpgl_origin;
+    };
+
+    struct PANEL_SYM_CHOOSER
+    {
+        int  sash_pos_h;
+        int  sash_pos_v;
+        int  width;
+        int  height;
+        bool keep_symbol;
+        bool place_all_units;
+    };
+
+    struct SIMULATOR
+    {
+        int plot_panel_width;
+        int plot_panel_height;
+        int signal_panel_height;
+        int cursors_panel_height;
+        bool white_background;
+        WINDOW_SETTINGS window;
+    };
+
+    EESCHEMA_SETTINGS();
+
+    virtual ~EESCHEMA_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    APPEARANCE m_Appearance;
+
+    AUTOPLACE_FIELDS m_AutoplaceFields;
+
+    DRAWING m_Drawing;
+
+    INPUT m_Input;
+
+    PAGE_SETTINGS m_PageSettings;
+
+    PANEL_ANNOTATE m_AnnotatePanel;
+
+    PANEL_BOM m_BomPanel;
+
+    PANEL_FIELD_EDITOR m_FieldEditorPanel;
+
+    PANEL_LIB_VIEW m_LibViewPanel;
+
+    PANEL_NETLIST m_NetlistPanel;
+
+    PANEL_PLOT m_PlotPanel;
+
+    PANEL_SYM_CHOOSER m_SymChooserPanel;
+
+    SELECTION m_Selection;
+
+    SIMULATOR m_Simulator;
+
+    bool m_RescueNeverShow;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "SchematicFrame"; }
+};
+
+
+#endif
diff --git a/eeschema/files-io.cpp b/eeschema/files-io.cpp
index 0ce0f02195..42d683b52d 100644
--- a/eeschema/files-io.cpp
+++ b/eeschema/files-io.cpp
@@ -43,6 +43,7 @@
 #include <wildcards_and_files_ext.h>
 #include <project_rescue.h>
 #include <eeschema_config.h>
+#include <eeschema_settings.h>
 #include <sch_legacy_plugin.h>
 #include <sch_eagle_plugin.h>
 #include <symbol_lib_table.h>
@@ -382,11 +383,9 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
 
             // Check to see whether some old library parts need to be rescued
             // Only do this if RescueNeverShow was not set.
-            wxConfigBase *config = Kiface().KifaceSettings();
-            bool rescueNeverShow = false;
-            config->Read( RescueNeverShowEntry, &rescueNeverShow, false );
+            auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
 
-            if( !rescueNeverShow )
+            if( !cfg->m_RescueNeverShow )
                 RescueSymbolLibTableProject( false );
         }
 
diff --git a/eeschema/general.h b/eeschema/general.h
index 9608b6fa80..5ef462acc6 100644
--- a/eeschema/general.h
+++ b/eeschema/general.h
@@ -148,7 +148,12 @@ int  GetSelectionThickness();
 void SetSelectionThickness( int aThickness );
 
 COLOR4D  GetLayerColor( SCH_LAYER_ID aLayer );
-void     SetLayerColor( COLOR4D aColor, SCH_LAYER_ID aLayer );
+
+/**
+ * Update the static layer color cache used by GetLayerColor()
+ * TODO(JE) Remove this once eeschema is refactored to not need s_layerColor[]
+ */
+void OnColorsChanged();
 
 // Color to draw selected items
 COLOR4D GetItemSelectedColor();
diff --git a/eeschema/lib_view_frame.cpp b/eeschema/lib_view_frame.cpp
index fdd937c139..d7da7d4e4f 100644
--- a/eeschema/lib_view_frame.cpp
+++ b/eeschema/lib_view_frame.cpp
@@ -31,6 +31,7 @@
 #include <dialog_choose_component.h>
 #include <eda_doc.h>
 #include <eeschema_id.h>
+#include <eeschema_settings.h>
 #include <fctsys.h>
 #include <kiface_i.h>
 #include <kiway.h>
@@ -42,6 +43,7 @@
 #include <symbol_lib_table.h>
 #include <symbol_tree_model_adapter.h>
 #include <pgm_base.h>
+#include <settings/settings_manager.h>
 #include <tool/tool_manager.h>
 #include <tool/action_toolbar.h>
 #include <tool/tool_dispatcher.h>
@@ -601,33 +603,18 @@ void LIB_VIEW_FRAME::DClickOnCmpList( wxCommandEvent& event )
 }
 
 
-#define LIBLIST_WIDTH_KEY "ViewLiblistWidth"
-#define CMPLIST_WIDTH_KEY "ViewCmplistWidth"
-#define CMPVIEW_SHOW_PINELECTRICALTYPE_KEY "ViewCmpShowPinElectricalType"
-
-
-void LIB_VIEW_FRAME::LoadSettings( wxConfigBase* aCfg )
+void LIB_VIEW_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
-    EDA_DRAW_FRAME::LoadSettings( aCfg );
+    auto cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
 
-    // Fetch display settings from Symbol Editor as the Symbol Viewer
-    // doesn't have its own config
-    wxString symbolEditor = LIB_EDIT_FRAME_NAME;
-    bool     btmp;
-    COLOR4D  wtmp;
-
-    if( aCfg->Read( symbolEditor + ShowGridEntryKeyword, &btmp ) )
-        SetGridVisibility( btmp );
-
-    if( wtmp.SetFromWxString( aCfg->Read( symbolEditor + GridColorEntryKeyword, wxT( "NONE" ) ) ) )
-        SetGridColor( wtmp );
+    EDA_DRAW_FRAME::LoadSettings( cfg );
 
     // Grid shape, etc.
-    GetGalDisplayOptions().ReadAppConfig( *aCfg, symbolEditor );
+    GetGalDisplayOptions().ReadWindowSettings( cfg->m_LibViewPanel.window );
 
-    aCfg->Read( LIBLIST_WIDTH_KEY, &m_libListWidth, 150 );
-    aCfg->Read( CMPLIST_WIDTH_KEY, &m_cmpListWidth, 150 );
-    m_showPinElectricalTypeName = aCfg->Read( CMPVIEW_SHOW_PINELECTRICALTYPE_KEY, true );
+    m_libListWidth = cfg->m_LibViewPanel.lib_list_width;
+    m_cmpListWidth = cfg->m_LibViewPanel.cmp_list_width;
+    m_showPinElectricalTypeName = cfg->m_LibViewPanel.show_pin_electrical_type;
 
     // Set parameters to a reasonable value.
     if( m_libListWidth > m_FrameSize.x/2 )
@@ -638,20 +625,28 @@ void LIB_VIEW_FRAME::LoadSettings( wxConfigBase* aCfg )
 }
 
 
-void LIB_VIEW_FRAME::SaveSettings( wxConfigBase* aCfg )
+void LIB_VIEW_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg)
 {
-    EDA_DRAW_FRAME::SaveSettings( aCfg );
+    auto cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
+
+    EDA_DRAW_FRAME::SaveSettings( cfg );
 
     if( m_libListWidth && m_libList )
-    {
         m_libListWidth = m_libList->GetSize().x;
-        aCfg->Write( LIBLIST_WIDTH_KEY, m_libListWidth );
-    }
 
     m_cmpListWidth = m_cmpList->GetSize().x;
-    aCfg->Write( CMPLIST_WIDTH_KEY, m_cmpListWidth );
 
-    aCfg->Write( CMPVIEW_SHOW_PINELECTRICALTYPE_KEY, m_showPinElectricalTypeName );
+    cfg->m_LibViewPanel.lib_list_width = m_libListWidth;
+    cfg->m_LibViewPanel.cmp_list_width = m_cmpListWidth;
+    cfg->m_LibViewPanel.show_pin_electrical_type = m_showPinElectricalTypeName;
+}
+
+
+WINDOW_SETTINGS* LIB_VIEW_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
+{
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+    return &cfg->m_LibViewPanel.window;
 }
 
 
diff --git a/eeschema/lib_view_frame.h b/eeschema/lib_view_frame.h
index 8e7334d8eb..cac2899d03 100644
--- a/eeschema/lib_view_frame.h
+++ b/eeschema/lib_view_frame.h
@@ -99,8 +99,11 @@ public:
     void ClickOnCmpList( wxCommandEvent& event );
     void OnSelectSymbol( wxCommandEvent& aEvent );
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
+
+    WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override;
+
     void CommonSettingsChanged( bool aEnvVarsChanged ) override;
 
     /**
diff --git a/eeschema/libedit/lib_edit_frame.cpp b/eeschema/libedit/lib_edit_frame.cpp
index 51069a7f4c..c20d95aec5 100644
--- a/eeschema/libedit/lib_edit_frame.cpp
+++ b/eeschema/libedit/lib_edit_frame.cpp
@@ -23,41 +23,44 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <base_screen.h>
+#include <class_library.h>
+#include <confirm.h>
+#include <eeschema_id.h>
+#include <eeschema_settings.h>
 #include <fctsys.h>
-#include <pgm_base.h>
+#include <general.h>
 #include <kiface_i.h>
 #include <kiway_express.h>
-#include <sch_draw_panel.h>
-#include <base_screen.h>
-#include <confirm.h>
-#include <general.h>
-#include <eeschema_id.h>
 #include <lib_edit_frame.h>
-#include <class_library.h>
 #include <lib_manager.h>
-#include <widgets/symbol_tree_pane.h>
-#include <widgets/lib_tree.h>
+#include <libedit_settings.h>
+#include <pgm_base.h>
+#include <sch_draw_panel.h>
+#include <sch_painter.h>
+#include <sch_view.h>
+#include <settings/settings_manager.h>
 #include <symbol_lib_table.h>
-#include <wildcards_and_files_ext.h>
-#include <wx/progdlg.h>
-#include <tool/tool_manager.h>
-#include <tool/tool_dispatcher.h>
 #include <tool/action_toolbar.h>
 #include <tool/common_control.h>
-#include <tool/picker_tool.h>
 #include <tool/common_tools.h>
+#include <tool/picker_tool.h>
+#include <tool/tool_dispatcher.h>
+#include <tool/tool_manager.h>
 #include <tool/zoom_tool.h>
 #include <tools/ee_actions.h>
-#include <tools/ee_selection_tool.h>
 #include <tools/ee_inspection_tool.h>
-#include <tools/lib_pin_tool.h>
+#include <tools/ee_point_editor.h>
+#include <tools/ee_selection_tool.h>
+#include <tools/lib_control.h>
+#include <tools/lib_drawing_tools.h>
 #include <tools/lib_edit_tool.h>
 #include <tools/lib_move_tool.h>
-#include <tools/lib_drawing_tools.h>
-#include <tools/lib_control.h>
-#include <tools/ee_point_editor.h>
-#include <sch_view.h>
-#include <sch_painter.h>
+#include <tools/lib_pin_tool.h>
+#include <widgets/lib_tree.h>
+#include <widgets/symbol_tree_pane.h>
+#include <wildcards_and_files_ext.h>
+#include <wx/progdlg.h>
 
 
 bool LIB_EDIT_FRAME::          m_showDeMorgan    = false;
@@ -123,7 +126,8 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
     icon.CopyFromBitmap( KiBitmap( icon_libedit_xpm ) );
     SetIcon( icon );
 
-    LoadSettings( config() );
+    m_settings = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
+    LoadSettings( m_settings );
 
     // Ensure axis are always drawn
     KIGFX::GAL_DISPLAY_OPTIONS& gal_opts = GetGalDisplayOptions();
@@ -203,10 +207,82 @@ LIB_EDIT_FRAME::~LIB_EDIT_FRAME()
     // current screen is destroyed in EDA_DRAW_FRAME
     SetScreen( m_dummyScreen );
 
+    auto libedit = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
+    Pgm().GetSettingsManager().Save( libedit );
+
     delete m_libMgr;
 }
 
 
+void LIB_EDIT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
+{
+    EDA_DRAW_FRAME::LoadSettings( aCfg );
+
+    auto cfg = dynamic_cast<LIBEDIT_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+
+    SetDefaultLineThickness( Mils2iu( cfg->m_Defaults.line_width ) );
+    SetDefaultPinLength( Mils2iu( cfg->m_Defaults.pin_length ) );
+    m_textPinNameDefaultSize = Mils2iu( cfg->m_Defaults.pin_name_size );
+    m_textPinNumDefaultSize = Mils2iu( cfg->m_Defaults.pin_num_size );
+    SetRepeatDeltaLabel( cfg->m_Repeat.label_delta );
+    SetRepeatPinStep( Mils2iu( cfg->m_Repeat.pin_step ) );
+    SetRepeatStep( wxPoint( cfg->m_Repeat.x_step, cfg->m_Repeat.y_step ) );
+    m_showPinElectricalTypeName = cfg->m_ShowPinElectricalType;
+    m_defaultLibWidth = cfg->m_LibWidth;
+
+    // TODO(JE) does libedit need its own TemplateFieldNames?
+    auto ee_settings = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
+    wxASSERT( ee_settings );
+    wxString templateFieldNames = ee_settings->m_Drawing.field_names;
+
+    if( !templateFieldNames.IsEmpty() )
+    {
+        TEMPLATE_FIELDNAMES_LEXER  lexer( TO_UTF8( templateFieldNames ) );
+
+        try
+        {
+            m_templateFieldNames.Parse( &lexer );
+        }
+        catch( const IO_ERROR& DBG( e ) )
+        {
+            // @todo show error msg
+            DBG( printf( "templatefieldnames parsing error: '%s'\n", TO_UTF8( e.What() ) ); )
+        }
+    }
+
+    auto painter = static_cast<KIGFX::SCH_PAINTER*>( GetCanvas()->GetView()->GetPainter() );
+    KIGFX::SCH_RENDER_SETTINGS* settings = painter->GetSettings();
+    settings->m_ShowPinsElectricalType = m_showPinElectricalTypeName;
+
+    // Hidden elements must be editable
+    settings->m_ShowHiddenText = true;
+    settings->m_ShowHiddenPins = true;
+    settings->m_ShowUmbilicals = false;
+}
+
+
+void LIB_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg)
+{
+    // aCfg will be EESCHEMA_SETTINGS because that's the parent FACE
+    // so we throw it away here and get our own settings
+
+    auto cfg = Pgm().GetSettingsManager().GetAppSettings<LIBEDIT_SETTINGS>();
+    EDA_DRAW_FRAME::SaveSettings( cfg );
+
+    cfg->m_Defaults.line_width    = Iu2Mils( GetDefaultLineThickness() );
+    cfg->m_Defaults.pin_length    = Iu2Mils( GetDefaultPinLength() );
+    cfg->m_Defaults.pin_name_size = Iu2Mils( GetPinNameDefaultSize() );
+    cfg->m_Defaults.pin_num_size  = Iu2Mils( GetPinNumDefaultSize() );
+    cfg->m_Repeat.label_delta     = GetRepeatDeltaLabel();
+    cfg->m_Repeat.pin_step        = Iu2Mils( GetRepeatPinStep() );
+    cfg->m_Repeat.x_step          = Iu2Mils( GetRepeatStep().x );
+    cfg->m_Repeat.y_step          = Iu2Mils( GetRepeatStep().y );
+    cfg->m_ShowPinElectricalType  = GetShowElectricalType();
+    cfg->m_LibWidth               = m_treePane->GetSize().x;
+}
+
+
 void LIB_EDIT_FRAME::setupTools()
 {
     // Create the manager and dispatcher & route draw panel events to the dispatcher
diff --git a/eeschema/libedit/lib_edit_frame.h b/eeschema/libedit/lib_edit_frame.h
index 5b82a40f38..d925ab3b37 100644
--- a/eeschema/libedit/lib_edit_frame.h
+++ b/eeschema/libedit/lib_edit_frame.h
@@ -43,6 +43,7 @@ class SYMBOL_TREE_PANE;
 class LIB_TREE_NODE;
 class LIB_ID;
 class LIB_MANAGER;
+class LIBEDIT_SETTINGS;
 
 
 /**
@@ -56,6 +57,7 @@ class LIB_EDIT_FRAME : public SCH_BASE_FRAME
                                             // has multiple units)
     SYMBOL_TREE_PANE*  m_treePane;          // component search tree widget
     LIB_MANAGER*       m_libMgr;            // manager taking care of temporary modifications
+    LIBEDIT_SETTINGS*  m_settings;          // Handle to the settings
 
     // The unit number to edit and show
     int m_unit;
@@ -255,8 +257,13 @@ public:
     void ReCreateVToolbar() override;
     void ReCreateOptToolbar() override;
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
+
+    LIBEDIT_SETTINGS* GetSettings()
+    {
+        return m_settings;
+    }
 
     /**
      * Trigger the wxCloseEvent, which is handled by the function given to EVT_CLOSE() macro:
diff --git a/eeschema/libedit/libedit_settings.cpp b/eeschema/libedit/libedit_settings.cpp
new file mode 100644
index 0000000000..47598d3e25
--- /dev/null
+++ b/eeschema/libedit/libedit_settings.cpp
@@ -0,0 +1,93 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#include <settings/common_settings.h>
+#include <settings/parameters.h>
+#include <settings/settings_manager.h>
+#include "libedit_settings.h"
+
+
+///! Update the schema version whenever a migration is required
+const int libeditSchemaVersion = 0;
+
+
+LIBEDIT_SETTINGS::LIBEDIT_SETTINGS() : APP_SETTINGS_BASE( "libedit", libeditSchemaVersion ),
+        m_Defaults(), m_Repeat(), m_ShowPinElectricalType( true ), m_LibWidth(),
+        m_EditComponentVisibleColumns()
+{
+    SetLegacyFilename( "eeschema" );
+
+    m_params.emplace_back( new PARAM<int>( "defaults.line_width", &m_Defaults.line_width, 6 ) );
+
+    m_params.emplace_back( new PARAM<int>( "defaults.pin_length", &m_Defaults.pin_length, 100 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "defaults.pin_name_size", &m_Defaults.pin_name_size, 50 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "defaults.pin_num_size", &m_Defaults.pin_num_size, 50 ) );
+
+    m_params.emplace_back( new PARAM<int>( "repeat.label_delta", &m_Repeat.label_delta, 1 ) );
+
+    m_params.emplace_back( new PARAM<int>( "repeat.pin_step", &m_Repeat.pin_step, 100 ) );
+
+    m_params.emplace_back( new PARAM<int>( "repeat.x_step", &m_Repeat.x_step, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "repeat.y_step", &m_Repeat.y_step, 100 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "show_pin_electrical_type",
+            &m_ShowPinElectricalType, true ) );
+
+    m_params.emplace_back( new PARAM<int>( "lib_table_width", &m_LibWidth, 250 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "edit_component_visible_columns",
+            &m_EditComponentVisibleColumns, "0 1 2 3 4 5 6 7" ) );
+}
+
+
+bool LIBEDIT_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    /*
+     * #define PinTableShownColumnsKey    wxT( "PinTableShownColumns" )
+        "0 1 2 3 4 8 9"
+
+     */
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacy<int>( aCfg, "DefaultWireWidth",      "defaults.line_width" );
+    ret &= fromLegacy<int>( aCfg, "DefaultPinLength",      "defaults.pin_length" );
+    ret &= fromLegacy<int>( aCfg, "LibeditPinNameSize",    "defaults.pin_name_size" );
+    ret &= fromLegacy<int>( aCfg, "LibeditPinNumSize",     "defaults.pin_num_size" );
+
+    ret &= fromLegacy<int>( aCfg, "LibeditRepeatLabelInc", "repeat.label_delta" );
+    ret &= fromLegacy<int>( aCfg, "LibeditPinRepeatStep",  "repeat.pin_step" );
+    ret &= fromLegacy<int>( aCfg, "LibeditRepeatStepX",    "repeat.x_step" );
+    ret &= fromLegacy<int>( aCfg, "LibeditRepeatStepY",    "repeat.y_step" );
+
+    ret &= fromLegacy<int>(  aCfg, "LibeditLibWidth",              "lib_table_width" );
+    ret &= fromLegacy<bool>( aCfg, "LibeditShowPinElectricalType", "show_pin_electrical_type" );
+
+    ret &= fromLegacyString( aCfg, "LibEditFieldsShownColumns", "edit_component_visible_columns" );
+
+    return ret;
+}
diff --git a/eeschema/libedit/libedit_settings.h b/eeschema/libedit/libedit_settings.h
new file mode 100644
index 0000000000..fc44c98d41
--- /dev/null
+++ b/eeschema/libedit/libedit_settings.h
@@ -0,0 +1,73 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#ifndef _LIBEDIT_SETTINGS_H
+#define _LIBEDIT_SETTINGS_H
+
+#include <settings/app_settings.h>
+
+
+class LIBEDIT_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+
+    struct DEFAULTS
+    {
+        int line_width;
+        int pin_length;
+        int pin_name_size;
+        int pin_num_size;
+    };
+
+    struct REPEAT
+    {
+        int label_delta;
+        int pin_step;
+        int x_step;
+        int y_step;
+    };
+
+    LIBEDIT_SETTINGS();
+
+    virtual ~LIBEDIT_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    DEFAULTS m_Defaults;
+
+    REPEAT m_Repeat;
+
+    bool m_ShowPinElectricalType;
+
+    int m_LibWidth;
+
+    wxString m_EditComponentVisibleColumns;
+
+    wxString m_PinTableVisibleColumns;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "LibeditFrame"; }
+};
+
+#endif
diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp
index 8f2d474855..c5abfc731f 100644
--- a/eeschema/sch_base_frame.cpp
+++ b/eeschema/sch_base_frame.cpp
@@ -87,7 +87,7 @@ SCH_BASE_FRAME::SCH_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aWindo
                                               // but this is an acceptable value
     m_repeatStep = wxPoint( Mils2iu( DEFAULT_REPEAT_OFFSET_X ),
                             Mils2iu( DEFAULT_REPEAT_OFFSET_Y ) );
-    m_repeatDeltaLabel = Mils2iu( DEFAULT_REPEAT_LABEL_INC );
+    m_repeatDeltaLabel = DEFAULT_REPEAT_LABEL_INC;
     m_showPinElectricalTypeName = false;
     m_repeatComponent = false;
     m_useAllUnits = false;
diff --git a/eeschema/sch_connection.cpp b/eeschema/sch_connection.cpp
index b24a338e1a..f85be41ac6 100644
--- a/eeschema/sch_connection.cpp
+++ b/eeschema/sch_connection.cpp
@@ -21,11 +21,11 @@
 #include <regex>
 #include <wx/tokenzr.h>
 
-#include <advanced_config.h>
 #include <connection_graph.h>
 #include <sch_component.h>
 #include <sch_pin.h>
 #include <sch_screen.h>
+#include <advanced_config.h>
 
 #include <sch_connection.h>
 
diff --git a/eeschema/sch_draw_panel.cpp b/eeschema/sch_draw_panel.cpp
index 5995dd2923..f38464dbe0 100644
--- a/eeschema/sch_draw_panel.cpp
+++ b/eeschema/sch_draw_panel.cpp
@@ -40,6 +40,8 @@
 #include <gal/graphics_abstraction_layer.h>
 #include <layers_id_colors_and_visibility.h>
 #include <math/vector2d.h>
+#include <pgm_base.h>
+#include <settings/settings_manager.h>
 #include <view/view.h>
 #include <view/view_controls.h>
 #include <view/wx_view_controls.h>
@@ -61,6 +63,7 @@ SCH_DRAW_PANEL::SCH_DRAW_PANEL( wxWindow* aParentWindow, wxWindowID aWindowId,
     m_gal->SetWorldUnitLength( SCH_WORLD_UNIT );
 
     m_painter.reset( new KIGFX::SCH_PAINTER( m_gal ) );
+    m_painter->GetSettings()->LoadColors( Pgm().GetSettingsManager().GetColorSettings() );
 
     m_view->SetPainter( m_painter.get() );
     m_view->SetScaleLimits( 1000.0, 0.0001 );    // This fixes the zoom in and zoom out limits
@@ -204,8 +207,5 @@ void SCH_DRAW_PANEL::onPaint( wxPaintEvent& aEvent )
     if( !m_gal->IsInitialized() || !m_gal->IsVisible() )
         return;
 
-    if( m_painter )
-        static_cast<KIGFX::SCH_PAINTER*>( m_painter.get() )->GetSettings()->ImportLegacyColors( nullptr );
-
     EDA_DRAW_PANEL_GAL::onPaint( aEvent );
 }
diff --git a/eeschema/sch_edit_frame.cpp b/eeschema/sch_edit_frame.cpp
index 9c994a2f47..29d694f022 100644
--- a/eeschema/sch_edit_frame.cpp
+++ b/eeschema/sch_edit_frame.cpp
@@ -22,7 +22,6 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <advanced_config.h>
 #include <base_units.h>
 #include <class_library.h>
 #include <confirm.h>
@@ -50,6 +49,7 @@
 #include <sch_edit_frame.h>
 #include <sch_painter.h>
 #include <sch_sheet.h>
+#include <advanced_config.h>
 #include <sim/sim_plot_frame.h>
 #include <symbol_lib_table.h>
 #include <tool/action_toolbar.h>
@@ -84,22 +84,6 @@ static void add_search_paths( SEARCH_STACK* aDst, const SEARCH_STACK& aSrc, int
 }
 
 
-// non-member so it can be moved easily, and kept REALLY private.
-// Do NOT Clear() in here.
-static void add_search_paths( SEARCH_STACK* aDst, wxConfigBase* aCfg, int aIndex )
-{
-    for( int i=1;  true;  ++i )
-    {
-        wxString key   = wxString::Format( wxT( "LibraryPath%d" ), i );
-        wxString upath = aCfg->Read( key, wxEmptyString );
-
-        if( !upath )
-            break;
-
-        aDst->AddPaths( upath, aIndex );
-    }
-}
-
 //-----<SCH "data on demand" functions>-------------------------------------------
 
 SEARCH_STACK* PROJECT::SchSearchS()
@@ -146,11 +130,6 @@ SEARCH_STACK* PROJECT::SchSearchS()
 
         // append all paths from aSList
         add_search_paths( ss, Kiface().KifaceSearch(), -1 );
-
-        // addLibrarySearchPaths( SEARCH_STACK* aSP, wxConfigBase* aCfg )
-        // This is undocumented, but somebody wanted to store !schematic!
-        // library search paths in the .kicad_common file?
-        add_search_paths( ss, Pgm().CommonSettings(), -1 );
     }
 
     return ss;
diff --git a/eeschema/sch_edit_frame.h b/eeschema/sch_edit_frame.h
index a6ae83e9f9..5aa861e44f 100644
--- a/eeschema/sch_edit_frame.h
+++ b/eeschema/sch_edit_frame.h
@@ -46,6 +46,7 @@
 
 class STATUS_TEXT_POPUP;
 
+class APP_SETTINGS_BASE;
 class SCH_ITEM;
 class EDA_ITEM;
 class SCH_LINE;
@@ -296,21 +297,8 @@ public:
         m_templateFieldNames.DeleteAllTemplateFieldNames();
     }
 
-    /**
-     * Return the Eeschema applications settings.
-     * <p>
-     * This replaces the old statically define list that had the project file settings and
-     * the application settings mixed together.  This was confusing and caused some settings
-     * to get saved and loaded incorrectly.  Currently, only the settings that are needed at
-     * start up by the main window are defined here.  There are other locally used settings
-     * scattered throughout the Eeschema source code.  If you need to define a configuration
-     * setting that need to be loaded at run time, this is the place to define it.
-     * </p>
-     */
-    std::vector<PARAM_CFG*>& GetConfigurationSettings();
-
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     void CreateScreens();
     void ReCreateHToolbar() override;
diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp
index 27c52a7f36..b2219d36d9 100644
--- a/eeschema/sch_painter.cpp
+++ b/eeschema/sch_painter.cpp
@@ -30,7 +30,6 @@
 #include <bezier_curves.h>
 #include <class_libentry.h>
 #include <class_library.h>
-#include <colors_design_settings.h>
 #include <connection_graph.h>
 #include <gal/graphics_abstraction_layer.h>
 #include <geometry/geometry_utils.h>
@@ -59,6 +58,7 @@
 #include <sch_no_connect.h>
 #include <sch_sheet.h>
 #include <sch_text.h>
+#include <settings/color_settings.h>
 #include <template_fieldnames.h>
 #include <view/view.h>
 
@@ -71,8 +71,6 @@ SCH_RENDER_SETTINGS::SCH_RENDER_SETTINGS() :
     m_ShowUnit( 0 ),
     m_ShowConvert( 0 )
 {
-    ImportLegacyColors( nullptr );
-
     m_ShowHiddenText = true;
     m_ShowHiddenPins = true;
     m_ShowPinsElectricalType = true;
@@ -81,15 +79,15 @@ SCH_RENDER_SETTINGS::SCH_RENDER_SETTINGS() :
 }
 
 
-void SCH_RENDER_SETTINGS::ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSettings )
+void SCH_RENDER_SETTINGS::LoadColors( const COLOR_SETTINGS* aSettings )
 {
     for( int layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; layer ++)
-        m_layerColors[ layer ] = ::GetLayerColor( static_cast<SCH_LAYER_ID>( layer ) );
+        m_layerColors[ layer ] = aSettings->GetColor( layer );
 
     for( int layer = GAL_LAYER_ID_START; layer < GAL_LAYER_ID_END; layer ++)
-        m_layerColors[ layer ] = ::GetLayerColor( static_cast<SCH_LAYER_ID>( layer ) );
+        m_layerColors[ layer ] = aSettings->GetColor( layer );
 
-    m_backgroundColor = ::GetLayerColor( LAYER_SCHEMATIC_BACKGROUND );
+    m_backgroundColor = aSettings->GetColor( LAYER_SCHEMATIC_BACKGROUND );
 }
 
 
@@ -152,8 +150,6 @@ bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer )
     auto item2 = static_cast<const EDA_ITEM*>( aItem );
     auto item = const_cast<EDA_ITEM*>( item2 );
 
-    m_schSettings.ImportLegacyColors( nullptr );
-
 #ifdef CONNECTIVITY_DEBUG
 
     auto sch_item = dynamic_cast<SCH_ITEM*>( item );
diff --git a/eeschema/sch_painter.h b/eeschema/sch_painter.h
index 49fa2b3310..94cad54bb1 100644
--- a/eeschema/sch_painter.h
+++ b/eeschema/sch_painter.h
@@ -73,8 +73,7 @@ public:
 
     SCH_RENDER_SETTINGS();
 
-    /// @copydoc RENDER_SETTINGS::ImportLegacyColors()
-    void ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSettings ) override;
+    void LoadColors( const COLOR_SETTINGS* aSettings ) override;
 
     /// @copydoc RENDER_SETTINGS::GetColor()
     virtual const COLOR4D& GetColor( const VIEW_ITEM* aItem, int aLayer ) const override;
diff --git a/eeschema/sch_preview_panel.cpp b/eeschema/sch_preview_panel.cpp
index d5620810ef..ca1fc6f1ae 100644
--- a/eeschema/sch_preview_panel.cpp
+++ b/eeschema/sch_preview_panel.cpp
@@ -31,6 +31,7 @@
 #include <sch_view.h>
 #include <sch_painter.h>
 #include <sch_edit_frame.h>
+#include <settings/settings_manager.h>
 #include <preview_items/selection_area.h>
 
 #include <functional>
@@ -52,6 +53,7 @@ SCH_PREVIEW_PANEL::SCH_PREVIEW_PANEL( wxWindow* aParentWindow, wxWindowID aWindo
     m_gal->SetWorldUnitLength( SCH_WORLD_UNIT );
 
     m_painter.reset( new KIGFX::SCH_PAINTER( m_gal ) );
+    m_painter->GetSettings()->LoadColors( Pgm().GetSettingsManager().GetColorSettings() );
 
     m_view->SetPainter( m_painter.get() );
     m_view->SetScaleLimits( 20000.0, 0.002 );
@@ -136,9 +138,6 @@ void SCH_PREVIEW_PANEL::Refresh( bool aEraseBackground, const wxRect* aRect )
 
 void SCH_PREVIEW_PANEL::onPaint( wxPaintEvent& aEvent )
 {
-    if( m_painter )
-        static_cast<KIGFX::SCH_PAINTER*>(m_painter.get())->GetSettings()->ImportLegacyColors( nullptr );
-
     if( IsShown() )
         EDA_DRAW_PANEL_GAL::onPaint( aEvent );
 }
diff --git a/eeschema/sch_preview_panel.h b/eeschema/sch_preview_panel.h
index 03c625b2cc..b340409508 100644
--- a/eeschema/sch_preview_panel.h
+++ b/eeschema/sch_preview_panel.h
@@ -50,13 +50,6 @@ public:
 
     ~SCH_PREVIEW_PANEL() override;
 
-    /**
-     * Function UseColorScheme
-     * Applies layer color settings.
-     * @param aSettings are the new settings.
-     */
-    void UseColorScheme( const COLORS_DESIGN_SETTINGS* aSettings );
-
     ///> @copydoc EDA_DRAW_PANEL_GAL::OnShow()
     void OnShow() override;
 
diff --git a/eeschema/sch_view.cpp b/eeschema/sch_view.cpp
index e426791e42..0734aadbbc 100644
--- a/eeschema/sch_view.cpp
+++ b/eeschema/sch_view.cpp
@@ -101,6 +101,7 @@ void SCH_VIEW::DisplaySheet( SCH_SCREEN *aScreen )
     m_worksheet->SetSheetNumber( aScreen->m_ScreenNumber );
     m_worksheet->SetSheetCount( aScreen->m_NumberOfScreens );
     m_worksheet->SetFileName( TO_UTF8( aScreen->GetFileName() ) );
+    m_worksheet->SetColorLayer( LAYER_SCHEMATIC_WORKSHEET );
 
     if( m_frame && m_frame->IsType( FRAME_SCH ) )
         m_worksheet->SetSheetName( TO_UTF8( m_frame->GetScreenDesc() ) );
diff --git a/eeschema/sim/sim_plot_frame.cpp b/eeschema/sim/sim_plot_frame.cpp
index 55568bf9e3..a80423067a 100644
--- a/eeschema/sim/sim_plot_frame.cpp
+++ b/eeschema/sim/sim_plot_frame.cpp
@@ -43,6 +43,7 @@
 #include <menus_helpers.h>
 #include <tool/tool_manager.h>
 #include <tools/ee_actions.h>
+#include <eeschema_settings.h>
 
 SIM_PLOT_TYPE operator|( SIM_PLOT_TYPE aFirst, SIM_PLOT_TYPE aSecond )
 {
@@ -231,39 +232,45 @@ SIM_PLOT_FRAME::~SIM_PLOT_FRAME()
         m_settingsDlg->Destroy();
 }
 
-// Keys for config save/read
-#define PLOT_PANEL_WIDTH_ENTRY "SimPlotPanelWidth"
-#define PLOT_PANEL_HEIGHT_ENTRY "SimPlotPanelHeight"
-#define SIGNALS_PANEL_HEIGHT_ENTRY "SimSignalPanelHeight"
-#define CURSORS_PANEL_HEIGHT_ENTRY "SimCursorsPanelHeight"
-#define PLOT_WITE_BG "SimPlotWhiteBg"
 
-void SIM_PLOT_FRAME::SaveSettings( wxConfigBase* aCfg )
+void SIM_PLOT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
-    // Save main frame size and position:
-    EDA_BASE_FRAME::SaveSettings( aCfg );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
 
-    // Save subwindows sizes
-    aCfg->Write( PLOT_PANEL_WIDTH_ENTRY, m_splitterLeftRight->GetSashPosition() );
-    aCfg->Write( PLOT_PANEL_HEIGHT_ENTRY, m_splitterPlotAndConsole->GetSashPosition() );
-    aCfg->Write( SIGNALS_PANEL_HEIGHT_ENTRY, m_splitterSignals->GetSashPosition() );
-    aCfg->Write( CURSORS_PANEL_HEIGHT_ENTRY, m_splitterTuneValues->GetSashPosition() );
-    aCfg->Write( PLOT_WITE_BG, m_plotUseWhiteBg );
+    EDA_BASE_FRAME::SaveSettings( cfg );
+
+    cfg->m_Simulator.plot_panel_width     = m_splitterLeftRight->GetSashPosition();
+    cfg->m_Simulator.plot_panel_height    = m_splitterPlotAndConsole->GetSashPosition();
+    cfg->m_Simulator.signal_panel_height  = m_splitterSignals->GetSashPosition();
+    cfg->m_Simulator.cursors_panel_height = m_splitterTuneValues->GetSashPosition();
+    cfg->m_Simulator.white_background     = m_plotUseWhiteBg;
 }
 
 
-void SIM_PLOT_FRAME::LoadSettings( wxConfigBase* aCfg )
+void SIM_PLOT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
-    // Read main frame size and position:
-    EDA_BASE_FRAME::LoadSettings( aCfg );
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+
+    EDA_BASE_FRAME::LoadSettings( cfg );
+
     SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
 
     // Read subwindows sizes (should be > 0 )
-    aCfg->Read( PLOT_PANEL_WIDTH_ENTRY, &m_splitterLeftRightSashPosition, -1 );
-    aCfg->Read( PLOT_PANEL_HEIGHT_ENTRY, &m_splitterPlotAndConsoleSashPosition, -1 );
-    aCfg->Read( SIGNALS_PANEL_HEIGHT_ENTRY, &m_splitterSignalsSashPosition, -1 );
-    aCfg->Read( CURSORS_PANEL_HEIGHT_ENTRY, &m_splitterTuneValuesSashPosition, -1 );
-    aCfg->Read( PLOT_WITE_BG, &m_plotUseWhiteBg, false );
+    m_splitterLeftRightSashPosition      = cfg->m_Simulator.plot_panel_width;
+    m_splitterPlotAndConsoleSashPosition = cfg->m_Simulator.plot_panel_height;
+    m_splitterSignalsSashPosition        = cfg->m_Simulator.signal_panel_height;
+    m_splitterTuneValuesSashPosition     = cfg->m_Simulator.cursors_panel_height;
+    m_plotUseWhiteBg                     = cfg->m_Simulator.white_background;
+}
+
+
+WINDOW_SETTINGS* SIM_PLOT_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
+{
+    auto cfg = dynamic_cast<EESCHEMA_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+    return &cfg->m_Simulator.window;
 }
 
 
diff --git a/eeschema/sim/sim_plot_frame.h b/eeschema/sim/sim_plot_frame.h
index 251a18bca6..0e5ead9fe7 100644
--- a/eeschema/sim/sim_plot_frame.h
+++ b/eeschema/sim/sim_plot_frame.h
@@ -190,9 +190,13 @@ public:
      */
     int GetPlotColorCount() { return m_colorList.size(); }
 
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
+
+    WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override;
+
 private:
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
 
     /** Give icons to menuitems of the main menubar
      */
diff --git a/eeschema/symbol_lib_table.cpp b/eeschema/symbol_lib_table.cpp
index e28ce38a20..e8b83c1ebe 100644
--- a/eeschema/symbol_lib_table.cpp
+++ b/eeschema/symbol_lib_table.cpp
@@ -30,6 +30,7 @@
 #include <lib_table_lexer.h>
 #include <pgm_base.h>
 #include <search_stack.h>
+#include <settings/settings_manager.h>
 #include <systemdirsappend.h>
 #include <symbol_lib_table.h>
 #include <class_libentry.h>
@@ -502,7 +503,7 @@ wxString SYMBOL_LIB_TABLE::GetGlobalTableFileName()
 {
     wxFileName fn;
 
-    fn.SetPath( GetKicadConfigPath() );
+    fn.SetPath( SETTINGS_MANAGER::GetUserSettingsPath() );
     fn.SetName( global_tbl_name );
 
     return fn.GetFullPath();
diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp
index 6963ff9db2..4a42b685e3 100644
--- a/eeschema/tools/sch_editor_control.cpp
+++ b/eeschema/tools/sch_editor_control.cpp
@@ -22,29 +22,34 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <kiway.h>
-#include <sch_view.h>
-#include <sch_edit_frame.h>
-#include <sch_sheet.h>
-#include <sch_line.h>
-#include <connection_graph.h>
-#include <erc.h>
-#include <netlist_object.h>
-#include <tool/tool_manager.h>
-#include <tool/picker_tool.h>
-#include <tools/ee_actions.h>
-#include <tools/sch_editor_control.h>
-#include <tools/ee_selection.h>
-#include <tools/ee_selection_tool.h>
-#include <advanced_config.h>
-#include <simulation_cursors.h>
-#include <sim/sim_plot_frame.h>
-#include <sch_legacy_plugin.h>
 #include <class_library.h>
 #include <confirm.h>
+#include <connection_graph.h>
+#include <dialogs/dialog_fields_editor_global.h>
+#include <dialogs/dialog_page_settings.h>
+#include <dialogs/dialog_paste_special.h>
+#include <erc.h>
+#include <fctsys.h>
+#include <invoke_sch_dialog.h>
+#include <kiway.h>
+#include <netlist_exporters/netlist_exporter_pspice.h>
+#include <netlist_object.h>
+#include <sch_edit_frame.h>
+#include <sch_legacy_plugin.h>
+#include <sch_line.h>
 #include <sch_painter.h>
+#include <sch_sheet.h>
+#include <sch_view.h>
+#include <advanced_config.h>
+#include <sim/sim_plot_frame.h>
+#include <simulation_cursors.h>
 #include <status_popup.h>
+#include <tool/picker_tool.h>
+#include <tool/tool_manager.h>
+#include <tools/ee_actions.h>
+#include <tools/ee_selection.h>
+#include <tools/ee_selection_tool.h>
+#include <tools/sch_editor_control.h>
 #include <ws_proxy_undo_item.h>
 #include <dialogs/dialog_page_settings.h>
 #include <dialogs/dialog_fields_editor_global.h>
diff --git a/eeschema/tools/sch_line_wire_bus_tool.cpp b/eeschema/tools/sch_line_wire_bus_tool.cpp
index 25cbd9f0f7..f94f5cc061 100644
--- a/eeschema/tools/sch_line_wire_bus_tool.cpp
+++ b/eeschema/tools/sch_line_wire_bus_tool.cpp
@@ -40,14 +40,14 @@
 #include <utility>
 #include <vector>
 
-#include <bitmaps.h>
-#include <advanced_config.h>
 #include <base_screen.h>
 #include <base_struct.h>
+#include <bitmaps.h>
 #include <core/typeinfo.h>
 #include <eda_text.h>
 #include <layers_id_colors_and_visibility.h>
 #include <math/vector2d.h>
+#include <advanced_config.h>
 #include <tool/actions.h>
 #include <tool/conditional_menu.h>
 #include <tool/selection.h>
diff --git a/eeschema/widgets/symbol_preview_widget.cpp b/eeschema/widgets/symbol_preview_widget.cpp
index 69d0cef10e..a1fe8f9c16 100644
--- a/eeschema/widgets/symbol_preview_widget.cpp
+++ b/eeschema/widgets/symbol_preview_widget.cpp
@@ -29,6 +29,8 @@
 #include <pgm_base.h>
 #include <sch_painter.h>
 #include <eda_draw_frame.h>
+#include <eeschema_settings.h>
+#include <settings/settings_manager.h>
 
 
 SYMBOL_PREVIEW_WIDGET::SYMBOL_PREVIEW_WIDGET( wxWindow* aParent, KIWAY& aKiway,
@@ -37,12 +39,10 @@ SYMBOL_PREVIEW_WIDGET::SYMBOL_PREVIEW_WIDGET( wxWindow* aParent, KIWAY& aKiway,
     m_kiway( aKiway ),
     m_preview( nullptr ), m_status( nullptr ), m_statusSizer( nullptr ), m_previewItem( nullptr )
 {
-    wxString eeschemaFrameKey( SCH_EDIT_FRAME_NAME );
+    auto common_settings = Pgm().GetCommonSettings();
+    auto app_settings = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
 
-    std::unique_ptr<wxConfigBase> eeschemaConfig = GetNewConfig( Pgm().App().GetAppName() );
-    wxConfigBase&                 commonConfig = *Pgm().CommonSettings();
-
-    m_galDisplayOptions.ReadConfig( commonConfig, *eeschemaConfig, eeschemaFrameKey, this );
+    m_galDisplayOptions.ReadConfig( *common_settings, app_settings->m_Window, this );
 
     EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = aCanvasType;
 
diff --git a/eeschema/widgets/widget_eeschema_color_config.cpp b/eeschema/widgets/widget_eeschema_color_config.cpp
index f031d60f58..4bc5f4f18a 100644
--- a/eeschema/widgets/widget_eeschema_color_config.cpp
+++ b/eeschema/widgets/widget_eeschema_color_config.cpp
@@ -30,6 +30,9 @@
 #include <sch_draw_panel.h>
 #include <sch_view.h>
 #include <general.h>
+#include <painter.h>
+#include <pgm_base.h>
+#include <settings/settings_manager.h>
 
 #include "widget_eeschema_color_config.h"
 #include <dialogs/dialog_color_picker.h>
@@ -92,7 +95,7 @@ static COLORBUTTON miscColorButtons[] = {
     { _( "ERC error" ),           LAYER_ERC_ERR },
     { _( "Brightened" ),          LAYER_BRIGHTENED },
     { _( "Hidden items" ),        LAYER_HIDDEN },
-    { _( "Worksheet" ),           LAYER_WORKSHEET },
+    { _( "Worksheet" ),           LAYER_SCHEMATIC_WORKSHEET },
     { _( "Cursor" ),              LAYER_SCHEMATIC_CURSOR },
     { _( "Grid" ),                LAYER_SCHEMATIC_GRID },
     { _( "Background" ),          LAYER_SCHEMATIC_BACKGROUND },
@@ -159,7 +162,7 @@ void WIDGET_EESCHEMA_COLOR_CONFIG::CreateControls()
             rowBoxSizer = new wxBoxSizer( wxHORIZONTAL );
             columnBoxSizer->Add( rowBoxSizer, 0, wxGROW | wxALL, 0 );
 
-            COLOR4D color = GetLayerColor( SCH_LAYER_ID( buttons->m_Layer ) );
+            COLOR4D color = m_drawFrame->GetLayerColor( SCH_LAYER_ID( buttons->m_Layer ) );
             currentColors[ buttons->m_Layer ] = color;
 
             wxMemoryDC iconDC;
@@ -260,10 +263,24 @@ bool WIDGET_EESCHEMA_COLOR_CONFIG::TransferDataFromControl()
         }
     }
 
-    for( SCH_LAYER_ID clyr = SCH_LAYER_ID_START; clyr < SCH_LAYER_ID_END; ++clyr )
-        SetLayerColor( currentColors[ clyr ], clyr );
+    COLOR_SETTINGS* color_settings = Pgm().GetSettingsManager().GetColorSettings();
 
-    SetLayerColor( currentColors[ LAYER_WORKSHEET ], (SCH_LAYER_ID) LAYER_WORKSHEET );
+    for( SCH_LAYER_ID clyr = SCH_LAYER_ID_START; clyr < SCH_LAYER_ID_END; ++clyr )
+    {
+        // Do not allow non-background layers to be completely white.
+        // This ensures the BW printing recognizes that the colors should be printed black.
+        if( currentColors[ clyr ] == COLOR4D::WHITE && clyr != LAYER_SCHEMATIC_BACKGROUND )
+            currentColors[ clyr ].Darken( 0.01 );
+
+        color_settings->SetColor( clyr, currentColors[ clyr ] );
+    }
+
+    auto settings = m_drawFrame->GetCanvas()->GetView()->GetPainter()->GetSettings();
+    settings->LoadColors( color_settings );
+
+    Pgm().GetSettingsManager().SaveColorSettings( color_settings, "schematic" );
+
+    OnColorsChanged();
 
     return true;
 }
diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt
index 783548191c..9f9b6d765b 100644
--- a/gerbview/CMakeLists.txt
+++ b/gerbview/CMakeLists.txt
@@ -45,7 +45,7 @@ set( GERBVIEW_SRCS
     excellon_read_drill_file.cpp
     export_to_pcbnew.cpp
     files.cpp
-    gerbview_config.cpp
+    gerbview_settings.cpp
     gerbview_frame.cpp
     job_file_reader.cpp
     menubar.cpp
@@ -72,7 +72,6 @@ set( GERBVIEW_EXTRA_SRCS
     ${CMAKE_SOURCE_DIR}/common/eda_text.cpp
     ${CMAKE_SOURCE_DIR}/common/widgets/layer_box_selector.cpp
     ${CMAKE_SOURCE_DIR}/common/lset.cpp
-    ${CMAKE_SOURCE_DIR}/common/settings.cpp
     ${CMAKE_SOURCE_DIR}/pcbnew/layer_widget.cpp
     ${CMAKE_SOURCE_DIR}/common/page_info.cpp
 )
diff --git a/gerbview/dialogs/dialog_print_gerbview.cpp b/gerbview/dialogs/dialog_print_gerbview.cpp
index dc7714e102..6b68ed99ad 100644
--- a/gerbview/dialogs/dialog_print_gerbview.cpp
+++ b/gerbview/dialogs/dialog_print_gerbview.cpp
@@ -38,17 +38,8 @@
 #include <tools/gerbview_actions.h>
 #include <tools/gerbview_control.h>
 
-///@{
-/// \ingroup config
-
+// TODO(JE)
 #define OPTKEY_LAYERBASE             wxT( "PlotLayer_%d" )
-#define OPTKEY_PRINT_X_FINESCALE_ADJ wxT( "PrintXFineScaleAdj" )
-#define OPTKEY_PRINT_Y_FINESCALE_ADJ wxT( "PrintYFineScaleAdj" )
-#define OPTKEY_PRINT_SCALE           wxT( "PrintScale" )
-#define OPTKEY_PRINT_PAGE_FRAME      wxT( "PrintPageFrame" )
-#define OPTKEY_PRINT_MONOCHROME_MODE wxT( "PrintMonochrome" )
-
-///@}
 
 
 class DIALOG_PRINT_GERBVIEW : public DIALOG_PRINT_GENERIC
diff --git a/gerbview/gbr_layout.h b/gerbview/gbr_layout.h
index 4b1bc627e4..19d3350ea7 100644
--- a/gerbview/gbr_layout.h
+++ b/gerbview/gbr_layout.h
@@ -32,7 +32,6 @@
 #define GBR_LAYOUT_H
 
 
-#include <colors_design_settings.h>
 #include <common.h>                         // PAGE_INFO
 #include <gerbview.h>                       // GERBER_DRAWLAYERS_COUNT
 #include <title_block.h>
diff --git a/gerbview/gerbview.cpp b/gerbview/gerbview.cpp
index 8d8edf82bf..3d37a30ed8 100644
--- a/gerbview/gerbview.cpp
+++ b/gerbview/gerbview.cpp
@@ -29,10 +29,12 @@
 #include <fctsys.h>
 #include <gerbview.h>
 #include <gerbview_frame.h>
+#include <gerbview_settings.h>
 #include <gestfich.h>
 #include <kiface_i.h>
 #include <nlohmann/json.hpp>
 #include <pgm_base.h>
+#include <settings/settings_manager.h>
 #include <wildcards_and_files_ext.h>
 
 using json = nlohmann::json;
@@ -133,6 +135,8 @@ PGM_BASE& Pgm()
 
 bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
 {
+    InitSettings( new GERBVIEW_SETTINGS );
+    aProgram->GetSettingsManager().RegisterSettings( KifaceSettings() );
     start_common( aCtlBits );
     return true;
 }
diff --git a/gerbview/gerbview_config.cpp b/gerbview/gerbview_config.cpp
deleted file mode 100644
index 6c123153d0..0000000000
--- a/gerbview/gerbview_config.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
- * Copyright (C) 2009 Wayne Stambaugh <stambaughw@verizon.net>
- * Copyright (C) 1992-2011 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 2
- * 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, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-#include <fctsys.h>
-#include <id.h>
-#include <common.h>
-#include <config_params.h>
-#include <gerbview_frame.h>
-#include <widgets/paged_dialog.h>
-#include <dialogs/panel_gerbview_settings.h>
-#include <dialogs/panel_gerbview_display_options.h>
-#include <panel_hotkeys_editor.h>
-
-
-void GERBVIEW_FRAME::InstallPreferences( PAGED_DIALOG* aParent,
-                                         PANEL_HOTKEYS_EDITOR* aHotkeysPanel )
-{
-    wxTreebook* book = aParent->GetTreebook();
-
-    book->AddPage( new wxPanel( book ), _( "Gerbview" ) );
-    book->AddSubPage( new PANEL_GERBVIEW_DISPLAY_OPTIONS( this, book ), _( "Display Options" ) );
-    book->AddSubPage( new PANEL_GERBVIEW_SETTINGS( this, book ), _( "Editing Options" ) );
-
-    aHotkeysPanel->AddHotKeys( GetToolManager() );
-}
-
-
-std::vector<PARAM_CFG*>& GERBVIEW_FRAME::GetConfigurationSettings()
-{
-    if( !m_configSettings.empty() )
-        return m_configSettings;
-
-    m_configSettings.push_back( new PARAM_CFG_INT(
-                            true, wxT( "DrawModeOption" ),
-                            &m_displayMode, 2, 0, 2 ) );
-    m_configSettings.push_back( new PARAM_CFG_SETCOLOR(
-                            true, wxT( "DCodeColorEx" ),
-                            &g_ColorsSettings.m_LayersColors[LAYER_DCODES], WHITE ) );
-    m_configSettings.push_back( new PARAM_CFG_SETCOLOR(
-                            true, wxT( "NegativeObjectsColorEx" ),
-                            &g_ColorsSettings.m_LayersColors[LAYER_NEGATIVE_OBJECTS], DARKGRAY ) );
-    m_configSettings.push_back( new PARAM_CFG_SETCOLOR(
-                            true, wxT( "GridColorEx" ),
-                            &g_ColorsSettings.m_LayersColors[LAYER_GERBVIEW_GRID], DARKGRAY ) );
-    m_configSettings.push_back( new PARAM_CFG_SETCOLOR(
-                            true, wxT( "WorksheetColorEx" ),
-                            &g_ColorsSettings.m_LayersColors[ LAYER_WORKSHEET], DARKRED ) );
-    m_configSettings.push_back( new PARAM_CFG_SETCOLOR(
-                            true, wxT( "BackgroundColorEx" ),
-                            &g_ColorsSettings.m_LayersColors[LAYER_PCB_BACKGROUND], BLACK ) );
-    m_configSettings.push_back( new PARAM_CFG_BOOL(
-                            true, wxT( "DisplayPolarCoordinates" ),
-                            &m_PolarCoords, false ) );
-
-    // Default colors for layers 0 to 31
-    static const COLOR4D color_default[] = {
-        COLOR4D( GREEN ),     COLOR4D( BLUE ),         COLOR4D( LIGHTGRAY ), COLOR4D( MAGENTA ),
-        COLOR4D( RED ),       COLOR4D( DARKGREEN ),    COLOR4D( BROWN ),     COLOR4D( MAGENTA ),
-        COLOR4D( LIGHTGRAY ), COLOR4D( BLUE ),         COLOR4D( GREEN ),     COLOR4D( CYAN ),
-        COLOR4D( LIGHTRED ),  COLOR4D( LIGHTMAGENTA ), COLOR4D( YELLOW ),    COLOR4D( RED ),
-        COLOR4D( BLUE ),      COLOR4D( BROWN ),        COLOR4D( LIGHTCYAN ), COLOR4D( RED ),
-        COLOR4D( MAGENTA ),   COLOR4D( CYAN ),         COLOR4D( BROWN ),     COLOR4D( MAGENTA ),
-        COLOR4D( LIGHTGRAY ), COLOR4D( BLUE ),         COLOR4D( GREEN ),     COLOR4D( DARKCYAN ),
-        COLOR4D( YELLOW ),    COLOR4D( LIGHTMAGENTA ), COLOR4D( YELLOW ),    COLOR4D( LIGHTGRAY ),
-    };
-
-    // List of keywords used as identifiers in config.
-    // They *must* be static const and not temporarily created,
-    // because the parameter list that use these keywords does not store them,
-    // just points to them.
-    static const wxChar* keys[] = {
-        wxT("ColorLayer0Ex"),  wxT("ColorLayer1Ex"),  wxT("ColorLayer2Ex"),  wxT("ColorLayer3Ex"),
-        wxT("ColorLayer4Ex"),  wxT("ColorLayer5Ex"),  wxT("ColorLayer6Ex"),  wxT("ColorLayer7Ex"),
-        wxT("ColorLayer8Ex"),  wxT("ColorLayer9Ex"),  wxT("ColorLayer10Ex"), wxT("ColorLayer11Ex"),
-        wxT("ColorLayer12Ex"), wxT("ColorLayer13Ex"), wxT("ColorLayer14Ex"), wxT("ColorLayer15Ex"),
-        wxT("ColorLayer16Ex"), wxT("ColorLayer17Ex"), wxT("ColorLayer18Ex"), wxT("ColorLayer19Ex"),
-        wxT("ColorLayer20Ex"), wxT("ColorLayer21Ex"), wxT("ColorLayer22Ex"), wxT("ColorLayer23Ex"),
-        wxT("ColorLayer24Ex"), wxT("ColorLayer25Ex"), wxT("ColorLayer26Ex"), wxT("ColorLayer27Ex"),
-        wxT("ColorLayer28Ex"), wxT("ColorLayer29Ex"), wxT("ColorLayer30Ex"), wxT("ColorLayer31Ex"),
-    };
-
-    wxASSERT( arrayDim(keys) == arrayDim(color_default) );
-    wxASSERT( arrayDim(keys) <= arrayDim(g_ColorsSettings.m_LayersColors) && arrayDim(keys) <= arrayDim(color_default) );
-
-    for( unsigned i = 0; i < arrayDim(keys);  ++i )
-    {
-        COLOR4D* prm = &g_ColorsSettings.m_LayersColors[ GERBER_DRAW_LAYER( i ) ];
-
-        PARAM_CFG_SETCOLOR* prm_entry =
-            new PARAM_CFG_SETCOLOR( true, keys[i], prm, color_default[i] );
-
-        m_configSettings.push_back( prm_entry );
-    }
-
-    return m_configSettings;
-}
diff --git a/gerbview/gerbview_draw_panel_gal.cpp b/gerbview/gerbview_draw_panel_gal.cpp
index ec1ac9670a..052cd2bb1c 100644
--- a/gerbview/gerbview_draw_panel_gal.cpp
+++ b/gerbview/gerbview_draw_panel_gal.cpp
@@ -23,10 +23,10 @@
 #include <gerbview_painter.h>
 #include <ws_proxy_view_item.h>
 
-#include <colors_design_settings.h>
 #include <gerbview_frame.h>
 #include <gbr_display_options.h>
 #include <gal/graphics_abstraction_layer.h>
+#include <settings/settings_manager.h>
 
 #include <gerber_file_image.h>
 #include <gerber_file_image_list.h>
@@ -52,16 +52,17 @@ EDA_DRAW_PANEL_GAL( aParentWindow, aWindowId, aPosition, aSize, aOptions, aGalTy
 
     setDefaultLayerDeps();
 
-
     // Load display options (such as filled/outline display of items).
     auto frame = static_cast< GERBVIEW_FRAME* >( GetParentEDAFrame() );
 
     if( frame )
     {
         auto& displ_opts = frame->GetDisplayOptions();
-        static_cast<KIGFX::GERBVIEW_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() )
-                                                     ->LoadDisplayOptions( displ_opts );
-        UseColorScheme( frame->m_colorsSettings );
+        auto rs = static_cast<KIGFX::GERBVIEW_RENDER_SETTINGS*>(
+                m_view->GetPainter()->GetSettings() );
+
+        rs->LoadDisplayOptions( displ_opts );
+        rs->LoadColors( Pgm().GetSettingsManager().GetColorSettings() );
     }
 }
 
@@ -71,14 +72,6 @@ GERBVIEW_DRAW_PANEL_GAL::~GERBVIEW_DRAW_PANEL_GAL()
 }
 
 
-void GERBVIEW_DRAW_PANEL_GAL::UseColorScheme( const COLORS_DESIGN_SETTINGS* aSettings )
-{
-    KIGFX::GERBVIEW_RENDER_SETTINGS* rs;
-    rs = static_cast<KIGFX::GERBVIEW_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() );
-    rs->ImportLegacyColors( aSettings );
-}
-
-
 void GERBVIEW_DRAW_PANEL_GAL::SetHighContrastLayer( int aLayer )
 {
     // Set display settings for high contrast mode
diff --git a/gerbview/gerbview_draw_panel_gal.h b/gerbview/gerbview_draw_panel_gal.h
index 1b8c43444f..0d8ff43a09 100644
--- a/gerbview/gerbview_draw_panel_gal.h
+++ b/gerbview/gerbview_draw_panel_gal.h
@@ -40,13 +40,6 @@ public:
 
     virtual ~GERBVIEW_DRAW_PANEL_GAL();
 
-    /**
-     * Function UseColorScheme
-     * Applies layer color settings.
-     * @param aSettings are the new settings.
-     */
-    void UseColorScheme( const COLORS_DESIGN_SETTINGS* aSettings );
-
     ///> @copydoc EDA_DRAW_PANEL_GAL::SetHighContrastLayer()
     virtual void SetHighContrastLayer( int aLayer ) override;
 
diff --git a/gerbview/gerbview_frame.cpp b/gerbview/gerbview_frame.cpp
index 54d67ee6f8..a89243510c 100644
--- a/gerbview/gerbview_frame.cpp
+++ b/gerbview/gerbview_frame.cpp
@@ -36,7 +36,10 @@
 #include <DCodeSelectionbox.h>
 #include <gerbview_layer_widget.h>
 #include <gerbview_draw_panel_gal.h>
+#include <gerbview_settings.h>
 #include <gal/graphics_abstraction_layer.h>
+#include <settings/common_settings.h>
+#include <settings/settings_manager.h>
 #include <tool/tool_manager.h>
 #include <tool/action_toolbar.h>
 #include <tool/tool_dispatcher.h>
@@ -49,17 +52,12 @@
 #include <view/view.h>
 #include <gerbview_painter.h>
 #include <geometry/shape_poly_set.h>
+#include <widgets/paged_dialog.h>
+#include <dialogs/panel_gerbview_settings.h>
+#include <dialogs/panel_gerbview_display_options.h>
+#include <panel_hotkeys_editor.h>
 
 
-// Config keywords
-static const wxString   cfgShowPageSizeOption( wxT( "PageSizeOpt" ) );
-static const wxString   cfgShowDCodes( wxT( "ShowDCodesOpt" ) );
-static const wxString   cfgShowNegativeObjects( wxT( "ShowNegativeObjectsOpt" ) );
-static const wxString   cfgShowBorderAndTitleBlock( wxT( "ShowBorderAndTitleBlock" ) );
-
-// Colors for layers and items
-COLORS_DESIGN_SETTINGS g_ColorsSettings( FRAME_GERBER );
-
 GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ):
     EDA_DRAW_FRAME( aKiway, aParent, FRAME_GERBER, wxT( "GerbView" ),
         wxDefaultPosition, wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, GERBVIEW_FRAME_NAME ),
@@ -67,7 +65,6 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ):
     m_drillFileHistory( DEFAULT_FILE_HISTORY_SIZE, ID_GERBVIEW_DRILL_FILE1 ),
     m_jobFileHistory( DEFAULT_FILE_HISTORY_SIZE, ID_GERBVIEW_JOB_FILE1 )
 {
-    m_colorsSettings = &g_ColorsSettings;
     m_gerberLayout = NULL;
     m_zoomLevelCoeff = ZOOM_FACTOR( 110 );   // Adjusted to roughly displays zoom level = 1
                                              // when the screen shows a 1:1 image
@@ -88,9 +85,7 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ):
     SHAPE_POLY_SET dummy;   // A ugly trick to force the linker to include
                             // some methods in code and avoid link errors
 
-    int fileHistorySize;
-    Pgm().CommonSettings()->Read( FILE_HISTORY_SIZE_KEY, &fileHistorySize,
-                                  DEFAULT_FILE_HISTORY_SIZE );
+    int fileHistorySize = Pgm().GetCommonSettings()->m_System.file_history_size;
     m_drillFileHistory.SetMaxFiles( fileHistorySize );
     m_zipFileHistory.SetMaxFiles( fileHistorySize );
     m_jobFileHistory.SetMaxFiles( fileHistorySize );
@@ -312,77 +307,44 @@ bool GERBVIEW_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
 }
 
 
-void GERBVIEW_FRAME::LoadSettings( wxConfigBase* aCfg )
+void GERBVIEW_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_DRAW_FRAME::LoadSettings( aCfg );
 
-    // was: wxGetApp().ReadCurrentSetupValues( GetConfigurationSettings() );
-    wxConfigLoadSetups( aCfg, GetConfigurationSettings() );
+    GERBVIEW_SETTINGS* cfg = dynamic_cast<GERBVIEW_SETTINGS*>( aCfg );
 
-    bool tmp;
-    aCfg->Read( cfgShowBorderAndTitleBlock, &tmp, false );
-    SetElementVisibility( LAYER_WORKSHEET, tmp );
+    SetElementVisibility( LAYER_WORKSHEET, cfg->m_Appearance.show_border_and_titleblock );
 
     PAGE_INFO pageInfo( wxT( "GERBER" ) );
-    wxString pageType;
-
-    aCfg->Read( cfgShowPageSizeOption, &pageType, wxT( "GERBER" ) );
-    pageInfo.SetType( pageType );
+    pageInfo.SetType( cfg->m_Appearance.page_type );
     SetPageSettings( pageInfo );
 
-    aCfg->Read( cfgShowDCodes, &tmp, true );
-    SetElementVisibility( LAYER_DCODES, tmp );
-    aCfg->Read( cfgShowNegativeObjects, &tmp, false );
-    SetElementVisibility( LAYER_NEGATIVE_OBJECTS, tmp );
+    SetElementVisibility( LAYER_DCODES, cfg->m_Appearance.show_dcodes );
+    SetElementVisibility( LAYER_NEGATIVE_OBJECTS, cfg->m_Appearance.show_negative_objects );
 
-    // because we have more than one file history, we must read this one
-    // using a specific path
-    aCfg->SetPath( wxT( "drl_files" ) );
-    m_drillFileHistory.Load( *aCfg );
-    aCfg->SetPath( wxT( ".." ) );
-
-    // because we have more than one file history, we must read this one
-    // using a specific path
-    aCfg->SetPath( wxT( "zip_files" ) );
-    m_zipFileHistory.Load( *aCfg );
-    aCfg->SetPath( wxT( ".." ) );
-
-    // because we have more than one file history, we must read this one
-    // using a specific path
-    aCfg->SetPath( "job_files" );
-    m_jobFileHistory.Load( *aCfg );
-    aCfg->SetPath( wxT( ".." ) );
+    m_drillFileHistory.Load( cfg->m_DrillFileHistory );
+    m_zipFileHistory.Load( cfg->m_ZipFileHistory );
+    m_jobFileHistory.Load( cfg->m_JobFileHistory );
 }
 
 
-void GERBVIEW_FRAME::SaveSettings( wxConfigBase* aCfg )
+void GERBVIEW_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_DRAW_FRAME::SaveSettings( aCfg );
 
-    // was: wxGetApp().SaveCurrentSetupValues( GetConfigurationSettings() );
-    wxConfigSaveSetups( aCfg, GetConfigurationSettings() );
+    GERBVIEW_SETTINGS* cfg = dynamic_cast<GERBVIEW_SETTINGS*>( aCfg );
 
-    aCfg->Write( cfgShowPageSizeOption, GetPageSettings().GetType() );
-    aCfg->Write( cfgShowBorderAndTitleBlock, m_showBorderAndTitleBlock );
-    aCfg->Write( cfgShowDCodes, IsElementVisible( LAYER_DCODES ) );
-    aCfg->Write( cfgShowNegativeObjects, IsElementVisible( LAYER_NEGATIVE_OBJECTS ) );
+    cfg->m_Appearance.page_type = GetPageSettings().GetType();
+    cfg->m_Appearance.show_border_and_titleblock = m_showBorderAndTitleBlock;
+    cfg->m_Appearance.show_dcodes = IsElementVisible( LAYER_DCODES );
+    cfg->m_Appearance.show_negative_objects = IsElementVisible( LAYER_NEGATIVE_OBJECTS );
 
-    // Save the drill file history list.
-    // Because we have  more than one file history, we must save this one
-    // in a specific path
-    aCfg->SetPath( wxT( "drl_files" ) );
-    m_drillFileHistory.Save( *aCfg );
-    aCfg->SetPath( wxT( ".." ) );
+    m_drillFileHistory.Save( &cfg->m_DrillFileHistory );
+    m_zipFileHistory.Save( &cfg->m_ZipFileHistory );
+    m_jobFileHistory.Save( &cfg->m_JobFileHistory );
 
-    // Save the zip file history list.
-    aCfg->SetPath( wxT( "zip_files" ) );
-    m_zipFileHistory.Save( *aCfg );
-    aCfg->SetPath( wxT( ".." ) );
-
-    // Save the job file history list.
-    aCfg->SetPath( "job_files" );
-    m_jobFileHistory.Save( *aCfg );
-    aCfg->SetPath( ".." );
+    COLOR_SETTINGS* cs = Pgm().GetSettingsManager().GetColorSettings();
+    Pgm().GetSettingsManager().SaveColorSettings( cs, "gerbview" );
 }
 
 
@@ -438,8 +400,10 @@ void GERBVIEW_FRAME::SetElementVisibility( int aLayerID, bool aNewState )
         break;
     }
 
-    case LAYER_WORKSHEET:
+    case LAYER_GERBVIEW_WORKSHEET:
         m_showBorderAndTitleBlock = aNewState;
+        // NOTE: LAYER_WORKSHEET always used for visibility, but the layer manager passes
+        // LAYER_GERBVIEW_WORKSHEET because of independent color control
         GetCanvas()->GetView()->SetLayerVisible( LAYER_WORKSHEET, aNewState );
         break;
 
@@ -473,8 +437,7 @@ void GERBVIEW_FRAME::applyDisplaySettingsToGAL()
     auto painter = static_cast<KIGFX::GERBVIEW_PAINTER*>( GetCanvas()->GetView()->GetPainter() );
     KIGFX::GERBVIEW_RENDER_SETTINGS* settings = painter->GetSettings();
     settings->LoadDisplayOptions( m_DisplayOptions );
-
-    settings->ImportLegacyColors( m_colorsSettings );
+    settings->LoadColors( Pgm().GetSettingsManager().GetColorSettings() );
 
     GetCanvas()->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
 }
@@ -746,11 +709,11 @@ bool GERBVIEW_FRAME::IsElementVisible( int aLayerID ) const
 {
     switch( aLayerID )
     {
-    case LAYER_DCODES:           return m_DisplayOptions.m_DisplayDCodes;
-    case LAYER_NEGATIVE_OBJECTS: return m_DisplayOptions.m_DisplayNegativeObjects;
-    case LAYER_GERBVIEW_GRID:    return IsGridVisible();
-    case LAYER_WORKSHEET:        return m_showBorderAndTitleBlock;
-    case LAYER_PCB_BACKGROUND:   return true;
+    case LAYER_DCODES:              return m_DisplayOptions.m_DisplayDCodes;
+    case LAYER_NEGATIVE_OBJECTS:    return m_DisplayOptions.m_DisplayNegativeObjects;
+    case LAYER_GERBVIEW_GRID:       return IsGridVisible();
+    case LAYER_WORKSHEET:           return m_showBorderAndTitleBlock;
+    case LAYER_GERBVIEW_BACKGROUND: return true;
 
     default:
         wxLogDebug( wxT( "GERBVIEW_FRAME::IsElementVisible(): bad arg %d" ), aLayerID );
@@ -804,9 +767,9 @@ COLOR4D GERBVIEW_FRAME::GetVisibleElementColor( int aLayerID )
     {
     case LAYER_NEGATIVE_OBJECTS:
     case LAYER_DCODES:
-    case LAYER_WORKSHEET:
-    case LAYER_PCB_BACKGROUND:
-        color = m_colorsSettings->GetItemColor( aLayerID );
+    case LAYER_GERBVIEW_WORKSHEET:
+    case LAYER_GERBVIEW_BACKGROUND:
+        color = Pgm().GetSettingsManager().GetColorSettings()->GetColor( aLayerID );
         break;
 
     case LAYER_GERBVIEW_GRID:
@@ -830,22 +793,24 @@ void GERBVIEW_FRAME::SetGridVisibility( bool aVisible )
 
 void GERBVIEW_FRAME::SetVisibleElementColor( int aLayerID, COLOR4D aColor )
 {
+    COLOR_SETTINGS* settings = Pgm().GetSettingsManager().GetColorSettings();
+
     switch( aLayerID )
     {
     case LAYER_NEGATIVE_OBJECTS:
     case LAYER_DCODES:
-    case LAYER_WORKSHEET:
-        m_colorsSettings->SetItemColor( aLayerID, aColor );
+    case LAYER_GERBVIEW_WORKSHEET:
+        settings->SetColor( aLayerID, aColor );
         break;
 
     case LAYER_GERBVIEW_GRID:
         SetGridColor( aColor );
-        m_colorsSettings->SetItemColor( aLayerID, aColor );
+        settings->SetColor( aLayerID, aColor );
         break;
 
-    case LAYER_PCB_BACKGROUND:
+    case LAYER_GERBVIEW_BACKGROUND:
         SetDrawBgColor( aColor );
-        m_colorsSettings->SetItemColor( aLayerID, aColor );
+        settings->SetColor( aLayerID, aColor );
         break;
 
     default:
@@ -865,13 +830,13 @@ COLOR4D GERBVIEW_FRAME::GetNegativeItemsColor()
 
 COLOR4D GERBVIEW_FRAME::GetLayerColor( int aLayer ) const
 {
-    return m_colorsSettings->GetLayerColor( aLayer );
+    return Pgm().GetSettingsManager().GetColorSettings()->GetColor( aLayer );
 }
 
 
 void GERBVIEW_FRAME::SetLayerColor( int aLayer, COLOR4D aColor )
 {
-    m_colorsSettings->SetLayerColor( aLayer, aColor );
+    Pgm().GetSettingsManager().GetColorSettings()->SetColor( aLayer, aColor );
     applyDisplaySettingsToGAL();
 }
 
@@ -919,7 +884,9 @@ void GERBVIEW_FRAME::SetPageSettings( const PAGE_INFO& aPageSettings )
         worksheet->SetSheetCount( 1 );
     }
 
-    // PCB_DRAW_PANEL_GAL takes ownership of the worksheet
+    worksheet->SetColorLayer( LAYER_GERBVIEW_WORKSHEET );
+
+    // Draw panel takes ownership of the worksheet
     drawPanel->SetWorksheet( worksheet );
 }
 
@@ -1155,6 +1122,20 @@ void GERBVIEW_FRAME::ActivateGalCanvas()
 }
 
 
+void GERBVIEW_FRAME::InstallPreferences( PAGED_DIALOG* aParent,
+                                         PANEL_HOTKEYS_EDITOR* aHotkeysPanel )
+{
+    wxTreebook* book = aParent->GetTreebook();
+
+    book->AddPage( new wxPanel( book ), _( "Gerbview" ) );
+    book->AddSubPage( new PANEL_GERBVIEW_DISPLAY_OPTIONS( this, book ), _( "Display Options" ) );
+    book->AddSubPage( new PANEL_GERBVIEW_SETTINGS( this, book ), _( "Editing Options" ) );
+
+    aHotkeysPanel->AddHotKeys( GetToolManager() );
+}
+
+
+
 void GERBVIEW_FRAME::setupTools()
 {
     // Create the manager and dispatcher & route draw panel events to the dispatcher
diff --git a/gerbview/gerbview_frame.h b/gerbview/gerbview_frame.h
index c43be063ea..9f66822da3 100644
--- a/gerbview/gerbview_frame.h
+++ b/gerbview/gerbview_frame.h
@@ -33,9 +33,6 @@
 #include <gbr_screen.h>
 #include <page_info.h>
 #include <gbr_display_options.h>
-#include <colors_design_settings.h>
-
-extern COLORS_DESIGN_SETTINGS g_ColorsSettings;
 
 #define NO_AVAILABLE_LAYERS UNDEFINED_LAYER
 
@@ -167,8 +164,6 @@ public:
     wxTextCtrl*             m_TextInfo;         // a wxTextCtrl used to display some info about
                                                 // gerber data (format..)
 
-    COLORS_DESIGN_SETTINGS* m_colorsSettings;
-
 private:
     std::vector<PARAM_CFG*> m_configSettings;
 
@@ -410,19 +405,9 @@ public:
      */
     void DisplayGridMsg();
 
-    /**
-     * Function GetConfigurationSettings
-     * Populates the GerbView applications settings list.
-     * (list of parameters that must be saved in GerbView parameters)
-     * Currently, only the settings that are needed at start up by the main window are
-     * defined here.  There are other locally used settings scattered throughout the
-     * GerbView source code (mainly in dialogs).  If you need to define a configuration
-     * setting that need to be loaded at run time, this is the place to define it.
-     */
-    std::vector<PARAM_CFG*>& GetConfigurationSettings( void );
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     void OnToggleShowLayerManager( wxCommandEvent& aEvent );
 
diff --git a/gerbview/gerbview_layer_widget.cpp b/gerbview/gerbview_layer_widget.cpp
index 3b36c292e0..e2062a27a3 100644
--- a/gerbview/gerbview_layer_widget.cpp
+++ b/gerbview/gerbview_layer_widget.cpp
@@ -36,6 +36,7 @@
 #include <view/view.h>
 #include <gerbview_painter.h>
 #include <gal/graphics_abstraction_layer.h>
+#include <settings/settings_manager.h>
 
 
 /*
@@ -97,13 +98,13 @@ void GERBER_LAYER_WIDGET::ReFillRender()
 
 #define RR  LAYER_WIDGET::ROW   // Render Row abreviation to reduce source width
 
-             // text                 id                      color     tooltip                 checked
-        RR( _( "DCodes" ),           LAYER_DCODES,           WHITE,    _( "Show DCodes identification" ) ),
-        RR( _( "Negative Objects" ), LAYER_NEGATIVE_OBJECTS, DARKGRAY, _( "Show negative objects in this color" ) ),
+             // text                 id                         color     tooltip                 checked
+        RR( _( "DCodes" ),           LAYER_DCODES,              WHITE,    _( "Show DCodes identification" ) ),
+        RR( _( "Negative Objects" ), LAYER_NEGATIVE_OBJECTS,    DARKGRAY, _( "Show negative objects in this color" ) ),
         RR(),
-        RR( _( "Grid" ),             LAYER_GERBVIEW_GRID,    WHITE,    _( "Show the (x,y) grid dots" ) ),
-        RR( _( "Worksheet" ),        LAYER_WORKSHEET,        DARKRED,  _( "Show worksheet") ),
-        RR( _( "Background" ),       LAYER_PCB_BACKGROUND,   BLACK,    _( "PCB Background" ), true, false )
+        RR( _( "Grid" ),             LAYER_GERBVIEW_GRID,       WHITE,    _( "Show the (x,y) grid dots" ) ),
+        RR( _( "Worksheet" ),        LAYER_GERBVIEW_WORKSHEET,  DARKRED,  _( "Show worksheet") ),
+        RR( _( "Background" ),       LAYER_GERBVIEW_BACKGROUND, BLACK,    _( "PCB Background" ), true, false )
     };
 
     for( unsigned row=0;  row<arrayDim(renderRows);  ++row )
@@ -254,7 +255,8 @@ void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, COLOR4D aColor )
     myframe->m_SelLayerBox->ResyncBitmapOnly();
 
     KIGFX::VIEW* view = myframe->GetCanvas()->GetView();
-    view->GetPainter()->GetSettings()->ImportLegacyColors( myframe->m_colorsSettings );
+    auto settings = Pgm().GetSettingsManager().GetColorSettings();
+    view->GetPainter()->GetSettings()->LoadColors( settings );
     view->UpdateLayerColor( GERBER_DRAW_LAYER( aLayer ) );
 
     myframe->GetCanvas()->Refresh();
@@ -298,8 +300,9 @@ void GERBER_LAYER_WIDGET::OnRenderColorChange( int aId, COLOR4D aColor )
     myframe->SetVisibleElementColor( aId, aColor );
 
     auto view = myframe->GetCanvas()->GetView();
+    auto settings = Pgm().GetSettingsManager().GetColorSettings();
 
-    view->GetPainter()->GetSettings()->ImportLegacyColors( myframe->m_colorsSettings );
+    view->GetPainter()->GetSettings()->LoadColors( settings );
     view->UpdateLayerColor( aId );
 
     view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );
diff --git a/gerbview/gerbview_painter.cpp b/gerbview/gerbview_painter.cpp
index 4b95f64fb9..389008b852 100644
--- a/gerbview/gerbview_painter.cpp
+++ b/gerbview/gerbview_painter.cpp
@@ -18,10 +18,9 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <colors_design_settings.h>
-
 #include <gerbview_painter.h>
 #include <gal/graphics_abstraction_layer.h>
+#include <settings/color_settings.h>
 #include <convert_basic_shapes_to_polygon.h>
 #include <convert_to_biu.h>
 #include <gerbview.h>
@@ -51,12 +50,18 @@ GERBVIEW_RENDER_SETTINGS::GERBVIEW_RENDER_SETTINGS()
 }
 
 
-void GERBVIEW_RENDER_SETTINGS::ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSettings )
+void GERBVIEW_RENDER_SETTINGS::LoadColors( const COLOR_SETTINGS* aSettings )
 {
+    size_t palette_size = aSettings->m_Palette.size();
+    size_t palette_idx = 0;
+
     for( int i = GERBVIEW_LAYER_ID_START;
          i < GERBVIEW_LAYER_ID_START + GERBER_DRAWLAYERS_COUNT; i++ )
     {
-        COLOR4D baseColor = aSettings->GetLayerColor( i );
+        COLOR4D baseColor = aSettings->GetColor( i );
+
+        if( baseColor == COLOR4D::UNSPECIFIED )
+            baseColor = aSettings->m_Palette[ ( palette_idx++ ) % palette_size ];
 
         if( m_diffMode )
             baseColor.a = 0.75;
@@ -68,10 +73,10 @@ void GERBVIEW_RENDER_SETTINGS::ImportLegacyColors( const COLORS_DESIGN_SETTINGS*
     }
 
     for( int i = LAYER_DCODES; i < GERBVIEW_LAYER_ID_END; i++ )
-        m_layerColors[i] = aSettings->GetLayerColor( i );
+        m_layerColors[i] = aSettings->GetColor( i );
 
     for( int i = GAL_LAYER_ID_START; i < GAL_LAYER_ID_END; i++ )
-        m_layerColors[i] = aSettings->GetLayerColor( i );
+        m_layerColors[i] = aSettings->GetColor( i );
 
     update();
 }
@@ -79,7 +84,6 @@ void GERBVIEW_RENDER_SETTINGS::ImportLegacyColors( const COLORS_DESIGN_SETTINGS*
 
 void GERBVIEW_RENDER_SETTINGS::LoadDisplayOptions( const GBR_DISPLAY_OPTIONS& aOptions )
 {
-
     m_spotFill          = aOptions.m_DisplayFlashedItemsFill;
     m_lineFill          = aOptions.m_DisplayLinesFill;
     m_polygonFill       = aOptions.m_DisplayPolygonsFill;
diff --git a/gerbview/gerbview_painter.h b/gerbview/gerbview_painter.h
index 9c5d3c6239..fcc7c3c09d 100644
--- a/gerbview/gerbview_painter.h
+++ b/gerbview/gerbview_painter.h
@@ -53,8 +53,7 @@ public:
 
     GERBVIEW_RENDER_SETTINGS();
 
-    /// @copydoc RENDER_SETTINGS::ImportLegacyColors()
-    void ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSettings ) override;
+    void LoadColors( const COLOR_SETTINGS* aSettings ) override;
 
     /**
      * Function LoadDisplayOptions
@@ -89,14 +88,14 @@ public:
         update();       // recompute other shades of the color
     }
 
-    const COLOR4D& GetBackgroundColor() override { return m_layerColors[ LAYER_PCB_BACKGROUND ]; }
+    const COLOR4D& GetBackgroundColor() override { return m_layerColors[ LAYER_GERBVIEW_BACKGROUND ]; }
 
     void SetBackgroundColor( const COLOR4D& aColor ) override
     {
-        m_layerColors[ LAYER_PCB_BACKGROUND ] = aColor;
+        m_layerColors[ LAYER_GERBVIEW_BACKGROUND ] = aColor;
     }
 
-    const COLOR4D& GetGridColor() override { return m_layerColors[ LAYER_GRID ]; }
+    const COLOR4D& GetGridColor() override { return m_layerColors[ LAYER_GERBVIEW_GRID ]; }
 
     const COLOR4D& GetCursorColor() override { return m_layerColors[ LAYER_CURSOR ]; }
 
diff --git a/gerbview/gerbview_settings.cpp b/gerbview/gerbview_settings.cpp
new file mode 100644
index 0000000000..85fda300e1
--- /dev/null
+++ b/gerbview/gerbview_settings.cpp
@@ -0,0 +1,117 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#include <gerbview_settings.h>
+#include <layers_id_colors_and_visibility.h>
+#include <pgm_base.h>
+#include <settings/common_settings.h>
+#include <settings/parameters.h>
+#include <wx/config.h>
+
+
+///! Update the schema version whenever a migration is required
+const int gerbviewSchemaVersion = 0;
+
+
+GERBVIEW_SETTINGS::GERBVIEW_SETTINGS() : APP_SETTINGS_BASE( "gerbview", gerbviewSchemaVersion )
+{
+    m_params.emplace_back( new PARAM<bool>( "appearance.show_border_and_titleblock",
+            &m_Appearance.show_border_and_titleblock, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "appearance.show_dcodes",
+            &m_Appearance.show_dcodes, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "appearance.show_negative_objects",
+            &m_Appearance.show_negative_objects, false ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "appearance.page_type",
+            &m_Appearance.page_type, "GERBER" ) );
+
+    m_params.emplace_back( new PARAM_LIST<wxString>( "system.drill_file_history",
+            &m_DrillFileHistory, {} ) );
+
+    m_params.emplace_back( new PARAM_LIST<wxString>( "system.zip_file_history",
+            &m_ZipFileHistory, {} ) );
+
+    m_params.emplace_back( new PARAM_LIST<wxString>( "system.job_file_history",
+            &m_JobFileHistory, {} ) );
+
+    m_params.emplace_back( new PARAM_LIST<int>( "gerber_to_pcb_layers",
+            &m_GerberToPcbLayerMapping, {} ) );
+}
+
+
+bool GERBVIEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacy<bool>( aCfg,
+        "ShowBorderAndTitleBlock", "appearance.show_border_and_titleblock" );
+
+    ret &= fromLegacy<bool>( aCfg, "ShowDCodesOpt",          "appearance.show_dcodes" );
+    ret &= fromLegacy<bool>( aCfg, "ShowNegativeObjectsOpt", "appearance.show_negative_objects" );
+    ret &= fromLegacyString( aCfg, "PageSizeOpt",            "appearance.page_type" );
+
+    auto migrate_files = [&] ( const std::string& aPath, const std::string& aDest )
+    {
+        int max_history_size = Pgm().GetCommonSettings()->m_System.file_history_size;
+        wxString file, key;
+        nlohmann::json js = nlohmann::json::array();
+
+        aCfg->SetPath( aPath );
+
+        for( int i = 0; i < max_history_size; i++ )
+        {
+            key.Printf( "file%d", i );
+            file = aCfg->Read( key, wxEmptyString );
+
+            if( !file.IsEmpty() )
+                js.emplace_back( file.ToStdString() );
+        }
+
+        aCfg->SetPath( ".." );
+
+        ( *this )[PointerFromString( aDest )] = js;
+    };
+
+    migrate_files( "drl_files", "system.drill_file_history" );
+    migrate_files( "zip_files", "system.zip_file_history" );
+    migrate_files( "job_files", "system.job_file_history" );
+
+    {
+        wxString key;
+        int value = 0;
+        nlohmann::json::json_pointer ptr = PointerFromString( "gerber_to_pcb_layers" );
+
+        ( *this )[ptr] = nlohmann::json::array();
+
+        for( int i = 0; i < GERBER_DRAWLAYERS_COUNT; i++ )
+        {
+            key.Printf( "GbrLyr%dToPcb", i );
+            aCfg->Read( key, &value, UNSELECTED_LAYER );
+            ( *this )[ptr].emplace_back( value );
+        }
+    }
+
+    return ret;
+}
diff --git a/gerbview/gerbview_settings.h b/gerbview/gerbview_settings.h
new file mode 100644
index 0000000000..55a624d5d2
--- /dev/null
+++ b/gerbview/gerbview_settings.h
@@ -0,0 +1,71 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#ifndef _GERBVIEW_SETTINGS_H
+#define _GERBVIEW_SETTINGS_H
+
+#include <settings/app_settings.h>
+
+
+class GERBVIEW_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+    struct APPEARANCE
+    {
+        bool show_border_and_titleblock;
+        bool show_dcodes;
+        bool show_negative_objects;
+        wxString page_type;
+    };
+
+    GERBVIEW_SETTINGS();
+
+    virtual ~GERBVIEW_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+public:
+
+    APPEARANCE m_Appearance;
+
+    int m_BoardLayersCount;
+
+    std::vector<wxString> m_DrillFileHistory;
+
+    std::vector<wxString> m_ZipFileHistory;
+
+    std::vector<wxString> m_JobFileHistory;
+
+    /**
+     * A list of GERBER_DRAWLAYERS_COUNT length containing a mapping of gerber layers
+     * to PCB layers, used when exporting gerbers to a PCB
+     */
+    std::vector<int> m_GerberToPcbLayerMapping;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "GerberFrame"; }
+
+};
+
+#endif
diff --git a/gerbview/menubar.cpp b/gerbview/menubar.cpp
index b8927af951..926573dd94 100644
--- a/gerbview/menubar.cpp
+++ b/gerbview/menubar.cpp
@@ -24,16 +24,16 @@
  */
 #include "gerbview_frame.h"
 
-#include <advanced_config.h>
-#include <kiface_i.h>
-#include <pgm_base.h>
 #include "gerbview_id.h"
+#include <kiface_i.h>
 #include <menus_helpers.h>
+#include <pgm_base.h>
+#include <advanced_config.h>
 #include <tool/actions.h>
-#include <tool/tool_manager.h>
 #include <tool/conditional_menu.h>
-#include <tools/gerbview_selection_tool.h>
+#include <tool/tool_manager.h>
 #include <tools/gerbview_actions.h>
+#include <tools/gerbview_selection_tool.h>
 
 
 void GERBVIEW_FRAME::ReCreateMenuBar()
diff --git a/gerbview/select_layers_to_pcb.cpp b/gerbview/select_layers_to_pcb.cpp
index f6a8588b11..f08dff4735 100644
--- a/gerbview/select_layers_to_pcb.cpp
+++ b/gerbview/select_layers_to_pcb.cpp
@@ -31,6 +31,7 @@
 #include <gerbview.h>
 #include <gerbview_frame.h>
 #include <gerbview_id.h>
+#include <gerbview_settings.h>
 #include <gerber_file_image.h>
 #include <gerber_file_image_list.h>
 
@@ -275,34 +276,30 @@ void LAYERS_MAP_DIALOG::OnResetClick( wxCommandEvent& event )
  */
 void LAYERS_MAP_DIALOG::OnStoreSetup( wxCommandEvent& event )
 {
-    wxConfigBase* config = Kiface().KifaceSettings();
-    config->Write( wxT("BrdLayersCount"), m_exportBoardCopperLayersCount );
+    auto config = dynamic_cast<GERBVIEW_SETTINGS*>( Kiface().KifaceSettings() );
+    config->m_BoardLayersCount = m_exportBoardCopperLayersCount;
+
+    config->m_GerberToPcbLayerMapping.clear();
 
-    wxString key;
     for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
     {
-        key.Printf( wxT("GbrLyr%dToPcb"), ii );
-        config->Write( key, m_layersLookUpTable[ii] );
+        config->m_GerberToPcbLayerMapping.push_back( m_layersLookUpTable[ii] );
     }
 }
 
 void LAYERS_MAP_DIALOG::OnGetSetup( wxCommandEvent& event )
 {
-    wxConfigBase* config = Kiface().KifaceSettings();
+    auto config = dynamic_cast<GERBVIEW_SETTINGS*>( Kiface().KifaceSettings() );
 
-    config->Read( wxT("BrdLayersCount"), &m_exportBoardCopperLayersCount );
+    m_exportBoardCopperLayersCount = config->m_BoardLayersCount;
     normalizeBrdLayersCount();
 
     int idx = ( m_exportBoardCopperLayersCount / 2 ) - 1;
     m_comboCopperLayersCount->SetSelection( idx );
 
-    wxString key;
     for( int ii = 0; ii < GERBER_DRAWLAYERS_COUNT; ++ii )
     {
-        key.Printf( wxT("GbrLyr%dToPcb"), ii );
-        int ilayer;
-        config->Read( key, &ilayer);
-        m_layersLookUpTable[ii] = ilayer;
+        m_layersLookUpTable[ii] = config->m_GerberToPcbLayerMapping[ ii ];
     }
 
     for( int ii = 0; ii < m_gerberActiveLayersCount; ii++ )
diff --git a/include/advanced_config.h b/include/advanced_config.h
index 386bbf80dd..53fb6032a1 100644
--- a/include/advanced_config.h
+++ b/include/advanced_config.h
@@ -88,6 +88,7 @@ public:
      */
     int m_coroutineStackSize;
 
+
 private:
     ADVANCED_CFG();
 
diff --git a/include/bin_mod.h b/include/bin_mod.h
index a516a76421..9277019e67 100644
--- a/include/bin_mod.h
+++ b/include/bin_mod.h
@@ -35,7 +35,7 @@
 #include <search_stack.h>
 #include <memory>
 
-class wxConfigBase;
+class APP_SETTINGS_BASE;
 class FILE_HISTORY;
 
 /**
@@ -54,9 +54,15 @@ struct BIN_MOD
     void Init();
     void End();
 
+    /**
+     * Takes ownership of a new application settings object
+     * @param aPtr is the settings object for this module
+     */
+    void InitSettings( APP_SETTINGS_BASE* aPtr ) { m_config = aPtr; }
+
     const char*         m_name;             ///< name of this binary module, static C string.
 
-    std::unique_ptr<wxConfigBase> m_config; ///< maybe from $HOME/.${m_name}
+    APP_SETTINGS_BASE*  m_config; ///< maybe from $HOME/.${m_name}
     FILE_HISTORY*       m_history;
     wxString            m_help_file;
 
diff --git a/include/board_design_settings.h b/include/board_design_settings.h
index 682115250c..734e126e98 100644
--- a/include/board_design_settings.h
+++ b/include/board_design_settings.h
@@ -233,14 +233,14 @@ public:
 
     // Variables used in footprint editing (default value in item/footprint creation)
 
-    wxString   m_RefDefaultText;            ///< Default ref text on fp creation
+    wxString   m_RefDefaultText;           ///< Default ref text on fp creation
                                             // if empty, use footprint name as default
     bool       m_RefDefaultVisibility;      ///< Default ref text visibility on fp creation
     int        m_RefDefaultlayer;           ///< Default ref text layer on fp creation
                                             // should be a PCB_LAYER_ID, but use an int
                                             // to save this param in config
 
-    wxString   m_ValueDefaultText;          ///< Default value text on fp creation
+    wxString   m_ValueDefaultText;         ///< Default value text on fp creation
                                             // if empty, use footprint name as default
     bool       m_ValueDefaultVisibility;    ///< Default value text visibility on fp creation
     int        m_ValueDefaultlayer;         ///< Default value text layer on fp creation
diff --git a/include/board_printout.h b/include/board_printout.h
index 020c58115b..de4e06e3cb 100644
--- a/include/board_printout.h
+++ b/include/board_printout.h
@@ -56,8 +56,8 @@ struct BOARD_PRINTOUT_SETTINGS : public PRINTOUT_SETTINGS
     LSET m_layerSet;                   ///< Layers to print
     bool m_mirror;                      ///< Print mirrored
 
-    void Load( wxConfigBase* aConfig ) override;
-    void Save( wxConfigBase* aConfig ) override;
+    void Load( APP_SETTINGS_BASE* aConfig ) override;
+    void Save( APP_SETTINGS_BASE* aConfig ) override;
 };
 
 /**
diff --git a/include/common.h b/include/common.h
index 81c20e80b5..6f07c86cac 100644
--- a/include/common.h
+++ b/include/common.h
@@ -209,35 +209,6 @@ bool EnsureFileDirectoryExists( wxFileName*     aTargetFullFileName,
 /// Put aPriorityPath in front of all paths in the value of aEnvVar.
 const wxString PrePendPath( const wxString& aEnvVar, const wxString& aPriorityPath );
 
-/**
- * Create a new wxConfig so we can put configuration files in a more proper place for each
- * platform.
- *
- * This is generally $HOME/.config/kicad/ in Linux according to the FreeDesktop specification at
- * http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html
- * The config object created here should be destroyed by the caller.
- *
- * @param aProgName is the name of the program calling this function - can be obtained by
- *  calling Pgm().App().GetAppName().  This will be the actual file name of the config file.
- * @return A pointer to a new wxConfigBase derived object is returned.  The caller is in charge
- *  of deleting it.
- */
-std::unique_ptr<wxConfigBase> GetNewConfig( const wxString& aProgName );
-
-/**
- * Return the user configuration path used to store KiCad's configuration files.
- *
- * The configuration path order of precedence is determined by the following criteria:
- *
- * - The value of the KICAD_CONFIG_HOME environment variable
- * - The value of the XDG_CONFIG_HOME environment variable.
- * - The result of the call to wxStandardPaths::GetUserConfigDir() with ".config" appended
- *   as required on Linux builds.
- *
- * @return A wxString containing the config path for Kicad
- */
-wxString GetKicadConfigPath();
-
 /**
  * Replace any environment variable references with their values.
  *
diff --git a/include/dpi_scaling.h b/include/dpi_scaling.h
index b81e982817..23430384a6 100644
--- a/include/dpi_scaling.h
+++ b/include/dpi_scaling.h
@@ -24,9 +24,10 @@
 #ifndef DPI_SCALING__H
 #define DPI_SCALING__H
 
-#include <wx/config.h>
 #include <wx/window.h>
 
+class COMMON_SETTINGS;
+
 /**
  * Class to handle configuration and automatic determination of the DPI
  * scale to use for canvases. This has several sources and the availability of
@@ -43,7 +44,7 @@ public:
      * @param aWindow a WX window to use for automatic DPI determination
      * @return the scaling factor (1.0 = no scaling)
      */
-    DPI_SCALING( wxConfigBase* aConfig, const wxWindow* aWindow );
+    DPI_SCALING( COMMON_SETTINGS* aConfig, const wxWindow* aWindow );
 
     /**
      * Get the DPI scale from all known sources in order:
@@ -91,7 +92,7 @@ private:
      * The configuration object to use to get/set user setting. nullptr
      * if only automatic options are wanted
      */
-    wxConfigBase* m_config;
+    COMMON_SETTINGS* m_config;
 
     /**
      * The WX window to use for WX's automatic DPI checking
diff --git a/include/eda_base_frame.h b/include/eda_base_frame.h
index fb3537f36f..36a5bd9a68 100644
--- a/include/eda_base_frame.h
+++ b/include/eda_base_frame.h
@@ -36,7 +36,6 @@
 
 #include <wx/socket.h>
 #include <wx/log.h>
-#include <wx/config.h>
 #include <wx/wxhtml.h>
 #include <wx/laywin.h>
 #include <wx/aui/aui.h>
@@ -76,7 +75,9 @@ class PAGED_DIALOG;
 class DIALOG_EDIT_LIBRARY_TABLES;
 class PANEL_HOTKEYS_EDITOR;
 class FILE_HISTORY;
-
+class SETTINGS_MANAGER;
+class APP_SETTINGS_BASE;
+struct WINDOW_SETTINGS;
 
 enum id_librarytype {
     LIBRARY_TYPE_EESCHEMA,
@@ -126,6 +127,8 @@ protected:
     wxString        m_configName;           // Prefix used to identify some params (frame size...)
                                             // and to name some config files (legacy hotkey files)
 
+    SETTINGS_MANAGER* m_settingsManager;
+
     TOOL_MANAGER*   m_toolManager;
     ACTIONS*        m_actions;
 
@@ -224,6 +227,8 @@ public:
         unitsChangeRefresh();
     }
 
+    SETTINGS_MANAGER* GetSettingsManager() const { return m_settingsManager; }
+
     /**
      * Return the MVC controller.
      */
@@ -306,10 +311,10 @@ public:
     void PrintMsg( const wxString& text );
 
     /**
-     * Returns the wxConfigBase used in SaveSettings(), and is overloaded in
+     * Returns the settings object used in SaveSettings(), and is overloaded in
      * KICAD_MANAGER_FRAME
      */
-    virtual wxConfigBase* config();
+    virtual APP_SETTINGS_BASE* config();
 
     /**
      * Function InstallPreferences
@@ -318,13 +323,27 @@ public:
      */
     virtual void InstallPreferences( PAGED_DIALOG* , PANEL_HOTKEYS_EDITOR* ) { }
 
+    /**
+     * Loads window settings from the given settings object
+     * Normally called by LoadSettings unless the window in question is a child window that
+     * stores its settings somewhere other than APP_SETTINGS_BASE::m_Window
+     */
+    void LoadWindowSettings( WINDOW_SETTINGS* aCfg );
+
+    /**
+     * Saves window settings to the given settings object
+     * Normally called by SaveSettings unless the window in question is a child window that
+     * stores its settings somewhere other than APP_SETTINGS_BASE::m_Window
+     */
+    void SaveWindowSettings( WINDOW_SETTINGS* aCfg );
+
     /**
      * Load common frame parameters from a configuration file.
      *
      * Don't forget to call the base method or your frames won't
      * remember their positions and sizes.
      */
-    virtual void LoadSettings( wxConfigBase* aCfg );
+    virtual void LoadSettings( APP_SETTINGS_BASE* aCfg );
 
     /**
      * Saves common frame parameters to a configuration data file.
@@ -333,7 +352,14 @@ public:
      * your derived SaveSettings() otherwise the frames won't remember their
      * positions and sizes.
      */
-    virtual void SaveSettings( wxConfigBase* aCfg );
+    virtual void SaveSettings( APP_SETTINGS_BASE* aCfg );
+
+    /**
+     * Returns a pointer to the window settings for this frame.
+     * By default, points to aCfg->m_Window for top-level frames.
+     * @param aCfg is this frame's config object
+     */
+    virtual WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg );
 
     /**
      * @return a base name prefix used in Load/Save settings to build the full name of keys
diff --git a/include/eda_draw_frame.h b/include/eda_draw_frame.h
index ae34f1651b..03b5571c92 100644
--- a/include/eda_draw_frame.h
+++ b/include/eda_draw_frame.h
@@ -38,6 +38,7 @@
 class wxSingleInstanceChecker;
 class ACTION_TOOLBAR;
 class TOOL_MENU;
+class APP_SETTINGS_BASE;
 
 using KIGFX::COLOR4D;
 
@@ -58,24 +59,6 @@ namespace KIGFX
 #define PCB_EDIT_FRAME_NAME                 wxT( "PcbFrame" )
 
 
-///@{
-/// \ingroup config
-
-/// User units
-#define UserUnitsEntryKeyword "Units"
-/// Nonzero to show grid (suffix)
-#define ShowGridEntryKeyword "ShowGrid"
-/// Grid color ID (suffix)
-#define GridColorEntryKeyword "GridColor"
-/// Most recently used grid size (suffix)
-#define LastGridSizeIdKeyword "_LastGridSize"
-
-/// The key to store the canvas type in config. This is the base key.
-/// can be a suffix if the canvas_type in config is specific to a frame
-#define CanvasTypeKeyBase "canvas_type"
-///@}
-
-
 /**
  * The base class for create windows for drawing purpose.  The Eeschema, Pcbnew and
  * GerbView main windows are just a few examples of classes derived from EDA_DRAW_FRAME.
@@ -163,12 +146,6 @@ protected:
      */
     bool saveCanvasTypeSetting( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType );
 
-    /** @return the key in KifaceSettings to store the canvas type.
-     * the base version returns only CanvasTypeKeyBase.
-     * Can be overriden to return a key specific of a frame name
-     */
-    virtual wxString GetCanvasTypeKey() { return CanvasTypeKeyBase; }
-
 public:
     EDA_DRAW_FRAME( KIWAY* aKiway, wxWindow* aParent,
                     FRAME_T aFrameType,
@@ -250,6 +227,11 @@ public:
      */
     virtual void SetDrawBgColor( COLOR4D aColor) { m_drawBgColor= aColor ; }
 
+    /**
+     * Helper to retrieve a layer color from the global color settings
+     */
+    COLOR4D GetLayerColor( SCH_LAYER_ID aLayer );
+
     bool ShowPageLimits() const { return m_showPageLimits; }
     void SetShowPageLimits( bool aShow ) { m_showPageLimits = aShow; }
 
@@ -418,9 +400,9 @@ public:
     void OnSockRequest( wxSocketEvent& evt );
     void OnSockRequestServer( wxSocketEvent& evt );
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
 
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     /**
      * Append a message to the message panel.
diff --git a/include/filehistory.h b/include/filehistory.h
index 5437bf41fc..643ecf778e 100644
--- a/include/filehistory.h
+++ b/include/filehistory.h
@@ -31,6 +31,8 @@
 #include <wx/menu.h>
 
 
+class APP_SETTINGS_BASE;
+
 /**
  * This class implements a file history object to store a list of files, that can then
  * be added to a menu.
@@ -48,6 +50,34 @@ public:
      */
     FILE_HISTORY( size_t aMaxFiles, int aBaseFileId );
 
+    /**
+     * Loads history from a JSON settings object
+     * @param aSettings is the settings object for this application
+     */
+    void Load( const APP_SETTINGS_BASE& aSettings );
+
+    /**
+     * Loads history from a list of strings
+     * @param aList is a list of filenames to load
+     */
+    void Load( const std::vector<wxString>& aList );
+
+    /**
+     * Saves history into a JSON settings object
+     * @param aSettings is the settings object to save into
+     */
+    void Save( APP_SETTINGS_BASE& aSettings );
+
+    /**
+     * Saves history into a list of strings
+     * @param aList is a pointer to a string vector to clear and fill with the file history
+     */
+    void Save( std::vector<wxString>* aList );
+
+    // Hide warnings about these virtual functions
+    using wxFileHistory::Load;
+    using wxFileHistory::Save;
+
     /**
      * Adds a file to the history.
      *
diff --git a/include/gal/color4d.h b/include/gal/color4d.h
index 7bb1db628a..e1ef28aa22 100644
--- a/include/gal/color4d.h
+++ b/include/gal/color4d.h
@@ -29,6 +29,7 @@
 
 #include <colors.h>
 #include <cassert>
+#include <nlohmann/json_fwd.hpp>
 
 namespace KIGFX
 {
@@ -320,6 +321,12 @@ const bool operator!=( const COLOR4D& lhs, const COLOR4D& rhs );
 /// Syntactic sugar for outputting colors to strings
 std::ostream &operator<<( std::ostream &aStream, COLOR4D const &aColor );
 
+// to allow json( COLOR4D )
+void to_json( nlohmann::json& aJson, const COLOR4D& aColor );
+
+// To allow json::get<COLOR4D>()
+void from_json( const nlohmann::json& aJson, COLOR4D& aColor );
+
 } // namespace KIGFX
 
 #endif /* COLOR4D_H_ */
diff --git a/include/gal/gal_display_options.h b/include/gal/gal_display_options.h
index 961bde78c1..de3e8443bf 100644
--- a/include/gal/gal_display_options.h
+++ b/include/gal/gal_display_options.h
@@ -26,7 +26,8 @@
 
 #include <observable.h>
 
-class wxConfigBase;
+class COMMON_SETTINGS;
+struct WINDOW_SETTINGS;
 class wxString;
 class wxWindow;
 
@@ -78,17 +79,16 @@ namespace KIGFX
 
         /**
          * Read GAL config options from applicaton-level config
-         * @param aCfg      the application config base
-         * @param aBaseName the application's GAL options key prefix
+         * @param aCfg      the window settings to load from
          */
-        void ReadAppConfig( wxConfigBase& aCfg, const wxString& aBaseName );
+        void ReadWindowSettings( WINDOW_SETTINGS& aCfg );
 
         /**
          * Read GAL config options from the common config store
-         * @param aCommonConfig the common config store
-         * @param aWindow       the wx parent window (used for DPI scaling)
+         * @param aCommonSettings the common config store
+         * @param aWindow         the wx parent window (used for DPI scaling)
          */
-        void ReadCommonConfig( wxConfigBase& aCommonConfig, wxWindow* aWindow );
+        void ReadCommonConfig( COMMON_SETTINGS& aCommonSettings, wxWindow* aWindow );
 
         /**
          * Read application and common configs
@@ -97,10 +97,10 @@ namespace KIGFX
          * @param aBaseName     the application's GAL options key prefix
          * @param aWindow       the wx parent window (used for DPI scaling)
          */
-        void ReadConfig( wxConfigBase& aCommonConfig, wxConfigBase& aAppCondfig,
-                const wxString& aBaseCfgName, wxWindow* aWindow );
+        void ReadConfig( COMMON_SETTINGS& aCommonConfig, WINDOW_SETTINGS& aWindowConfig,
+                wxWindow* aWindow );
 
-        void WriteConfig( wxConfigBase& aCfg, const wxString& aBaseName );
+        void WriteConfig( WINDOW_SETTINGS& aCfg );
 
         void NotifyChanged();
 
diff --git a/include/kiface_i.h b/include/kiface_i.h
index 55b6198b9e..6c54636249 100644
--- a/include/kiface_i.h
+++ b/include/kiface_i.h
@@ -100,7 +100,9 @@ public:
 
     const wxString Name()                               { return wxString::FromUTF8( m_bm.m_name ); }
 
-    wxConfigBase* KifaceSettings() const                { return m_bm.m_config.get(); }
+    APP_SETTINGS_BASE* KifaceSettings() const           { return m_bm.m_config; }
+
+    void InitSettings( APP_SETTINGS_BASE* aSettings )   { m_bm.InitSettings( aSettings ); }
 
     /**
      * Function StartFlags
diff --git a/include/kiway.h b/include/kiway.h
index 43186257b1..92646f83cd 100644
--- a/include/kiway.h
+++ b/include/kiway.h
@@ -129,7 +129,6 @@ as such!  As such, it is OK to use UTF8 characters:
 
 class wxConfigBase;
 class wxWindow;
-class wxConfigBase;
 class PGM_BASE;
 class KIWAY;
 class KIWAY_PLAYER;
diff --git a/include/layers_id_colors_and_visibility.h b/include/layers_id_colors_and_visibility.h
index 32c0190452..4b4352e687 100644
--- a/include/layers_id_colors_and_visibility.h
+++ b/include/layers_id_colors_and_visibility.h
@@ -266,6 +266,7 @@ enum SCH_LAYER_ID: int
     LAYER_BRIGHTENED,
     LAYER_HIDDEN,
     LAYER_SELECTION_SHADOWS,
+    LAYER_SCHEMATIC_WORKSHEET,
 
     SCH_LAYER_ID_END
 };
@@ -296,6 +297,7 @@ enum GERBVIEW_LAYER_ID: int
     LAYER_GERBVIEW_GRID,
     LAYER_GERBVIEW_AXES,
     LAYER_GERBVIEW_BACKGROUND,
+    LAYER_GERBVIEW_WORKSHEET,
 
     GERBVIEW_LAYER_ID_END
 };
@@ -306,8 +308,40 @@ enum GERBVIEW_LAYER_ID: int
 
 #define GERBER_DRAW_LAYER_INDEX( x ) ( x - GERBVIEW_LAYER_ID_START )
 
+// TODO(JE) Remove after we have color themes
+// Temporary virtual layers to store color themes for footprint editor
+enum FPEDIT_LAYER_ID : int
+{
+    FPEDIT_LAYER_ID_START = GERBVIEW_LAYER_ID_END,
+
+    // Reserve a copy of the board and netname layers...
+    FPEDIT_LAYER_ID_RESERVED = FPEDIT_LAYER_ID_START + ( 2 * PCB_LAYER_ID_COUNT ),
+
+    // And a copy of the GAL layers
+    FPEDIT_GAL_RESERVED = FPEDIT_LAYER_ID_RESERVED + ( GAL_LAYER_ID_END - GAL_LAYER_ID_START ),
+
+    FPEDIT_LAYER_ID_END
+};
+
+/// 3D Viewer virtual layers for color settings
+enum LAYER_3D_ID : int
+{
+        LAYER_3D_START = FPEDIT_LAYER_ID_END,
+
+        LAYER_3D_BACKGROUND_BOTTOM,
+        LAYER_3D_BACKGROUND_TOP,
+        LAYER_3D_BOARD,
+        LAYER_3D_COPPER,
+        LAYER_3D_SILKSCREEN_BOTTOM,
+        LAYER_3D_SILKSCREEN_TOP,
+        LAYER_3D_SOLDERMASK,
+        LAYER_3D_SOLDERPASTE,
+
+        LAYER_3D_END = LAYER_3D_SOLDERPASTE
+};
+
 /// Must update this if you add any enums after GerbView!
-#define LAYER_ID_COUNT GERBVIEW_LAYER_ID_END
+#define LAYER_ID_COUNT FPEDIT_LAYER_ID_END
 
 
 // Some elements do not have yet a visibility control
diff --git a/include/painter.h b/include/painter.h
index 7936b60978..3f8ada918d 100644
--- a/include/painter.h
+++ b/include/painter.h
@@ -36,7 +36,7 @@
 #include <memory>
 
 class EDA_ITEM;
-class COLORS_DESIGN_SETTINGS;
+class COLOR_SETTINGS;
 
 namespace KIGFX
 {
@@ -59,12 +59,7 @@ public:
     RENDER_SETTINGS();
     virtual ~RENDER_SETTINGS();
 
-    /**
-     * Function ImportLegacyColors
-     * Loads a list of color settings for layers.
-     * @param aSettings is a list of color settings.
-     */
-    virtual void ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSettings ) { }
+    virtual void LoadColors( const COLOR_SETTINGS* aSettings ) { }
 
     /**
      * Function SetActiveLayer
diff --git a/include/pcb_base_frame.h b/include/pcb_base_frame.h
index bcb98cbef2..4dd29eccf3 100644
--- a/include/pcb_base_frame.h
+++ b/include/pcb_base_frame.h
@@ -40,13 +40,14 @@
 #include <richio.h>
 #include <pcb_screen.h>
 #include <pcb_display_options.h>
-#include <pcb_general_settings.h>
 #include <pcb_draw_panel_gal.h>
 #include <lib_id.h>
 
 /* Forward declarations of classes. */
+class APP_SETTINGS_BASE;
 class BOARD;
 class BOARD_CONNECTED_ITEM;
+class COLOR_SETTINGS;
 class MODULE;
 class TRACK;
 class D_PAD;
@@ -58,6 +59,7 @@ class BOARD_DESIGN_SETTINGS;
 class ZONE_SETTINGS;
 class PCB_PLOT_PARAMS;
 class FP_LIB_TABLE;
+class PCBNEW_SETTINGS;
 
 /**
  * PCB_BASE_FRAME
@@ -76,7 +78,7 @@ protected:
 
     PCB_DISPLAY_OPTIONS     m_DisplayOptions;
 
-    PCB_GENERAL_SETTINGS    m_configSettings;
+    PCBNEW_SETTINGS*        m_Settings; // No ownership, just a shortcut
 
     void updateZoomSelectBox();
     virtual void unitsChangeRefresh() override;
@@ -158,6 +160,14 @@ public:
     virtual BOARD_DESIGN_SETTINGS& GetDesignSettings() const;
     virtual void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings );
 
+    /**
+     * Helper to retrieve the current color settings
+     * @return a pointer to the active COLOR_SETTINGS
+     */
+    COLOR_SETTINGS* ColorSettings();
+
+    PCBNEW_SETTINGS& Settings() { return *m_Settings; }
+
     void SetDrawBgColor( COLOR4D aColor ) override;
 
     /**
@@ -385,8 +395,10 @@ public:
         return GetScreen()->m_Active_Layer;
     }
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
+
+    PCBNEW_SETTINGS* GetSettings();
 
     void CommonSettingsChanged( bool aEnvVarsChanged ) override;
 
@@ -443,15 +455,6 @@ public:
     ///> @copydoc EDA_DRAW_FRAME::UseGalCanvas
     virtual void ActivateGalCanvas() override;
 
-    PCB_GENERAL_SETTINGS& Settings()
-    {
-        return m_configSettings;
-    }
-
-    ///> Key in KifaceSettings to store the canvas type.
-    static const wxChar AUTO_ZOOM_KEY[];
-    static const wxChar ZOOM_KEY[];
-
     DECLARE_EVENT_TABLE()
 };
 
diff --git a/include/pgm_base.h b/include/pgm_base.h
index fe19229a5d..c08045bd07 100644
--- a/include/pgm_base.h
+++ b/include/pgm_base.h
@@ -31,41 +31,22 @@
 #ifndef  PGM_BASE_H_
 #define  PGM_BASE_H_
 
+#include <bitmaps_png/bitmap_def.h>
 #include <map>
 #include <memory>
-#include <wx/filename.h>
 #include <search_stack.h>
+#include <wx/filename.h>
 #include <wx/gdicmn.h>
-#include <bitmaps_png/bitmap_def.h>
 
 
-///@{
-/// \ingroup config
-
-#define USE_ICONS_IN_MENUS_KEY          wxT( "UseIconsInMenus" )
-#define ICON_SCALE_KEY                  wxT( "IconScale" )
-#define CANVAS_SCALE_KEY                wxT( "CanvasScale" )
-#define AUTOSAVE_INTERVAL_KEY           wxT( "AutoSaveInterval" )
-#define ENBL_ZOOM_NO_CENTER_KEY         wxT( "ZoomNoCenter" )
-#define ENBL_MOUSEWHEEL_PAN_KEY         wxT( "MousewheelPAN" )
-#define MIDDLE_BUTT_PAN_LIMITED_KEY     wxT( "MiddleBtnPANLimited" )
-#define ENBL_AUTO_PAN_KEY               wxT( "AutoPAN" )
-#define FILE_HISTORY_SIZE_KEY           wxT( "FileHistorySize" )
-#define GAL_DISPLAY_OPTIONS_KEY         wxT( "GalDisplayOptions" )
-#define GAL_ANTIALIASING_MODE_KEY       wxT( "OpenGLAntialiasingMode" )
-#define CAIRO_ANTIALIASING_MODE_KEY     wxT( "CairoAntialiasingMode" )
-#define WARP_MOUSE_ON_MOVE_KEY           wxT( "MoveWarpsCursor" )
-#define IMMEDIATE_ACTIONS_KEY           wxT( "ImmediateActions" )
-#define PREFER_SELECT_TO_DRAG_KEY       wxT( "PreferSelectionToDragging" )
-
-///@}
-
-class wxConfigBase;
 class wxSingleInstanceChecker;
 class wxApp;
 class wxMenu;
 class wxWindow;
 
+class COMMON_SETTINGS;
+class SETTINGS_MANAGER;
+
 /**
  *   A small class to handle the list of existing translations.
  *   The locale translation is automatic.
@@ -191,7 +172,9 @@ public:
      */
     VTBL_ENTRY void MacOpenFile( const wxString& aFileName ) = 0;
 
-    VTBL_ENTRY wxConfigBase* CommonSettings() const { return m_common_settings.get(); }
+    VTBL_ENTRY SETTINGS_MANAGER& GetSettingsManager() const { return *m_settings_manager; }
+
+    VTBL_ENTRY COMMON_SETTINGS* GetCommonSettings() const;
 
     VTBL_ENTRY void SetEditorName( const wxString& aFileName );
 
@@ -359,19 +342,14 @@ public:
 
 protected:
 
-    /**
-     * Function loadCommonSettings
-     * loads the program (process) settings subset which are stored in .kicad_common
-     */
+    /// Loads internal settings from COMMON_SETTINGS
     void loadCommonSettings();
 
+    std::unique_ptr<SETTINGS_MANAGER> m_settings_manager;
+
     /// prevents multiple instances of a program from being run at the same time.
     wxSingleInstanceChecker* m_pgm_checker;
 
-    /// Configuration settings common to all KiCad program modules,
-    /// like as in $HOME/.kicad_common
-    std::unique_ptr<wxConfigBase> m_common_settings;
-
     /// full path to this program
     wxString        m_bin_dir;
 
diff --git a/include/plotter.h b/include/plotter.h
index 299b3ae9ed..c174971d4f 100644
--- a/include/plotter.h
+++ b/include/plotter.h
@@ -38,6 +38,7 @@
 #include <page_info.h>
 #include <eda_text.h>       // FILL_T
 
+class COLOR_SETTINGS;
 class SHAPE_POLY_SET;
 class SHAPE_LINE_CHAIN;
 class GBR_NETLIST_METADATA;
@@ -139,6 +140,10 @@ public:
         return colorMode;
     }
 
+    void SetColorSettings( COLOR_SETTINGS* aSettings ) { m_colors = aSettings; }
+
+    COLOR_SETTINGS* ColorSettings() { return m_colors; }
+
     virtual void SetPageSettings( const PAGE_INFO& aPageSettings );
 
     /**
@@ -600,6 +605,9 @@ protected:      // variables used in most of plotters:
     wxSize        paperSize;
 
     wxArrayString m_headerExtraLines;  /// a set of string to print in header file
+
+    /// Pointer to active color settings that is used for plotting
+    COLOR_SETTINGS* m_colors;
 };
 
 
diff --git a/include/printout.h b/include/printout.h
index 06d9d748c8..80f467259d 100644
--- a/include/printout.h
+++ b/include/printout.h
@@ -21,7 +21,7 @@
 
 #include <page_info.h>
 
-class wxConfigBase;
+class APP_SETTINGS_BASE;
 
 /**
  * PRINT_PARAMETERS
@@ -42,8 +42,8 @@ struct PRINTOUT_SETTINGS
     {
     }
 
-    virtual void Save( wxConfigBase* aConfig );
-    virtual void Load( wxConfigBase* aConfig );
+    virtual void Save( APP_SETTINGS_BASE* aConfig );
+    virtual void Load( APP_SETTINGS_BASE* aConfig );
 
     double m_scale;         ///< Printing scale
     bool   m_titleBlock;    ///< Print frame and title block
diff --git a/include/settings/app_settings.h b/include/settings/app_settings.h
new file mode 100644
index 0000000000..db4d7a390e
--- /dev/null
+++ b/include/settings/app_settings.h
@@ -0,0 +1,162 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 _APP_SETTINGS_H
+#define _APP_SETTINGS_H
+
+#include <gal/color4d.h>
+#include <settings/json_settings.h>
+
+/**
+ * Common cursor settings, available to every frame
+ */
+struct CURSOR_SETTINGS
+{
+    bool always_show_cursor;
+    bool fullscreen_cursor;
+};
+
+/**
+ * Common grid settings, available to every frame
+ */
+struct GRID_SETTINGS
+{
+    bool axes_enabled;
+    int last_size;
+    double line_width;
+    double min_spacing;
+    bool show;
+    int style;
+};
+
+/**
+ * Stores the common settings that are saved and loaded for each window / frame
+ */
+struct WINDOW_SETTINGS
+{
+    bool maximized;
+    wxString mru_path;
+    int size_x;
+    int size_y;
+    wxString perspective;
+    int pos_x;
+    int pos_y;
+
+    CURSOR_SETTINGS cursor;
+    GRID_SETTINGS grid;
+    bool auto_zoom;
+    double zoom;
+};
+
+/**
+ * APP_SETTINGS_BASE is a settings class that should be derived for each standalone KiCad
+ * application.  It stores settings that should exist for every app, but may be different from
+ * app to app depending on the user's preferences.
+ *
+ * COMMON_SETTINGS stores settings that are always the same across all applications.
+ */
+class APP_SETTINGS_BASE : public JSON_SETTINGS
+{
+public:
+
+
+    struct FIND_REPLACE
+    {
+        int                   flags;
+        wxString              find_string;
+        std::vector<wxString> find_history;
+        wxString              replace_string;
+        std::vector<wxString> replace_history;
+    };
+
+    struct GRAPHICS
+    {
+        int canvas_type;
+    };
+
+    struct LIB_TREE
+    {
+        int column_width;
+    };
+
+    struct PRINTING
+    {
+        bool   monochrome;
+        double scale;
+        bool   title_block;
+        std::vector<int> layers;      ///< List of enabled layers for printing
+    };
+
+    struct SYSTEM
+    {
+        bool                  first_run_shown;
+        int                   max_undo_items;
+        std::vector<wxString> file_history;
+        int                   units;
+    };
+
+    APP_SETTINGS_BASE( std::string aFilename, int aSchemaVersion );
+
+    virtual ~APP_SETTINGS_BASE() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aCfg ) override;
+
+public:
+    FIND_REPLACE m_FindReplace;
+
+    GRAPHICS m_Graphics;
+
+    LIB_TREE m_LibTree;
+
+    PRINTING m_Printing;
+
+    SYSTEM m_System;
+
+    WINDOW_SETTINGS m_Window;
+
+    ///! Local schema version for common app settings
+    int m_appSettingsSchemaVersion;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const { return std::string(); }
+
+    ///! Migrates the find/replace history string lists
+    void migrateFindReplace( wxConfigBase* aCfg );
+
+    /**
+     * Migrates legacy window settings into the JSON document
+     * @param aCfg is the wxConfig object to read from
+     * @param aFrameName is the prefix for window settings in the legacy config file
+     * @param aJsonPath is the prefix for storing window settings in the JSON file
+     * @return true if all settings were migrated
+     */
+    bool migrateWindowConfig( wxConfigBase* aCfg, const std::string& aFrameName,
+            const std::string& aJsonPath );
+
+    /**
+     * Adds parameters for the given window object
+     * @param aWindow is the target window settings object
+     * @param aJsonPath is the path to read parameters from
+     */
+    void addParamsForWindow( WINDOW_SETTINGS* aWindow, const std::string& aJsonPath );
+};
+
+#endif
diff --git a/include/settings/color_settings.h b/include/settings/color_settings.h
new file mode 100644
index 0000000000..854e718da6
--- /dev/null
+++ b/include/settings/color_settings.h
@@ -0,0 +1,158 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 _COLOR_SETTINGS_H
+#define _COLOR_SETTINGS_H
+
+#include <gal/color4d.h>
+#include <settings/json_settings.h>
+
+using KIGFX::COLOR4D;
+
+/**
+ * Color settings are a bit different than most of the settings objects in that there
+ * can be more than one of them loaded at once.
+ *
+ * Each COLOR_SETTINGS object corresponds to a single color scheme file on disk.
+ * The default color scheme is called "default" and will be created on first run.
+ *
+ * When users change color settings, they have the option of modifying the default scheme
+ * or saving their changes to a new color scheme file.
+ *
+ * Each COLOR_SETTINGS defines all the settings used across all parts of KiCad, but it's not
+ * necessary for the underlying theme file to contain all of them.  The color settings cascade,
+ * so if a user chooses a non-default scheme for a certain application, and that non-default
+ * scheme file is missing some color definitions, those will fall back to those from the "default"
+ * scheme (which is either loaded from disk or created if missing)
+ *
+ * Each application (eeschema, gerbview, pcbnew) can have a different active color scheme selected.
+ * The "child applications" (library editors) inherit from either eeschema or pcbnew.
+ */
+
+#include <settings/json_settings.h>
+#include <settings/parameters.h>
+
+/**
+ * For specifying whether to retrieve colors from the "pcbnew" or "fpedit" set.
+ * Can be removed once color themes exist.
+ */
+enum class COLOR_CONTEXT
+{
+    PCB,
+    FOOTPRINT
+};
+
+class COLOR_SETTINGS : public JSON_SETTINGS
+{
+public:
+    /**
+     * m_Pallete stores a list of colors that are used, in order, when a list of colors needs to be
+     * generated for an application.  For example, layer colors in GerbView, or default layer colors
+     * in PcbNew.
+     */
+    std::vector<COLOR4D> m_Palette;
+
+    explicit COLOR_SETTINGS( std::string aFilename = "user" );
+
+    virtual ~COLOR_SETTINGS() {}
+
+    bool MigrateFromLegacy( wxConfigBase* aCfg ) override;
+
+    COLOR4D GetColor( int aLayer ) const;
+
+    COLOR4D GetDefaultColor( int aLayer );
+
+    void SetColor( int aLayer, COLOR4D aColor );
+
+    // TODO(JE) remove once color themes exist
+    void SetColorContext( COLOR_CONTEXT aContext = COLOR_CONTEXT::PCB )
+    {
+        m_color_context = aContext;
+    }
+
+private:
+
+    wxString m_displayName;
+
+    /**
+     * Map of all layer colors.
+     * The key needs to be a valid layer ID, see layers_id_colors_and_visibility.h
+     */
+    std::unordered_map<int, COLOR4D> m_colors;
+
+    std::unordered_map<int, COLOR4D> m_defaultColors;
+
+    // TODO(JE) remove once color themes exist
+    COLOR_CONTEXT m_color_context;
+};
+
+class COLOR_MAP_PARAM : public PARAM_BASE
+{
+public:
+    COLOR_MAP_PARAM( const std::string& aJsonPath, int aMapKey, COLOR4D aDefault,
+                     std::unordered_map<int, COLOR4D>* aMap, bool aReadOnly = false ) :
+            PARAM_BASE( aJsonPath, aReadOnly ), m_key( aMapKey ), m_default( aDefault ),
+            m_map( aMap )
+    {}
+
+    void Load( JSON_SETTINGS* aSettings ) const override
+    {
+        if( m_readOnly )
+            return;
+
+        COLOR4D val = m_default;
+
+        try
+        {
+            val = aSettings->Get<COLOR4D>( m_path );
+        }
+        catch( ... )
+        {}
+
+        ( *m_map )[ m_key ] = val;
+    }
+
+    void Store( JSON_SETTINGS* aSettings) const override
+    {
+        aSettings->Set<COLOR4D>( m_path, ( *m_map )[ m_key ] );
+    }
+
+    int GetKey() const
+    {
+        return m_key;
+    }
+
+    COLOR4D GetDefault() const
+    {
+        return m_default;
+    }
+
+    virtual void SetDefault() override
+    {
+        ( *m_map )[ m_key ] = m_default;
+    }
+
+private:
+    int m_key;
+    COLOR4D m_default;
+    std::unordered_map<int, COLOR4D>* m_map;
+};
+
+#endif
diff --git a/include/settings/common_settings.h b/include/settings/common_settings.h
new file mode 100644
index 0000000000..a904577c36
--- /dev/null
+++ b/include/settings/common_settings.h
@@ -0,0 +1,93 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 _COMMON_SETTINGS_H
+#define _COMMON_SETTINGS_H
+
+#include <settings/json_settings.h>
+
+
+class COMMON_SETTINGS : public JSON_SETTINGS
+{
+public:
+    struct APPEARANCE
+    {
+        double canvas_scale;
+        int icon_scale;
+        bool use_icons_in_menus;
+    };
+
+    struct ENVIRONMENT
+    {
+        bool show_warning_dialog;
+        std::map<std::string, wxString> vars;
+    };
+
+    struct INPUT
+    {
+        bool auto_pan;
+        bool center_on_zoom;
+        bool immediate_actions;
+        bool mousewheel_pan;
+        bool prefer_select_to_drag;
+        bool warp_mouse_on_move;
+    };
+
+    struct GRAPHICS
+    {
+        int cairo_aa_mode;
+        int opengl_aa_mode;
+    };
+
+    struct SYSTEM
+    {
+        int autosave_interval;
+        wxString editor_name;
+        int file_history_size;
+        wxString language;
+        wxString pdf_viewer_name;
+        bool use_system_pdf_viewer;
+        wxString working_dir;
+    };
+
+    COMMON_SETTINGS();
+
+    virtual ~COMMON_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+public:
+    APPEARANCE m_Appearance;
+
+    ENVIRONMENT m_Env;
+
+    INPUT m_Input;
+
+    GRAPHICS m_Graphics;
+
+    SYSTEM m_System;
+
+    // TODO: These may not want to be in common
+    wxString m_3DLibsUrl;
+
+    wxString m_3DLibsDownloadPath;
+};
+
+#endif
diff --git a/include/settings/json_settings.h b/include/settings/json_settings.h
new file mode 100644
index 0000000000..c676ee1b25
--- /dev/null
+++ b/include/settings/json_settings.h
@@ -0,0 +1,227 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 _JSON_SETTINGS_H
+#define _JSON_SETTINGS_H
+
+#include <nlohmann/json.hpp>
+#include <utility>
+#include <wx/string.h>
+
+class wxConfigBase;
+class NESTED_SETTINGS;
+class PARAM_BASE;
+
+enum class SETTINGS_LOC {
+    USER,       ///< The main config directory (e.g. ~/.config/kicad/)
+    PROJECT,    ///< The settings directory inside a project folder
+    COLORS,     ///< The color scheme directory (e.g. ~/.config/kicad/colors/)
+    NESTED,     ///< Not stored in a file, but inside another JSON_SETTINGS
+};
+
+
+class JSON_SETTINGS : public nlohmann::json
+{
+public:
+    JSON_SETTINGS( const std::string& aFilename, SETTINGS_LOC aLocation, int aSchemaVersion,
+                   nlohmann::json aDefaultJson = nlohmann::json( {} ) ) :
+            JSON_SETTINGS( aFilename, aLocation, aSchemaVersion, true, true, aDefaultJson ) {}
+
+    JSON_SETTINGS( const std::string& aFilename, SETTINGS_LOC aLocation, int aSchemaVersion,
+                   bool aCreateIfMissing, bool aWriteFile,
+                   nlohmann::json aDefaultJson = nlohmann::json( {} ) );
+
+    virtual ~JSON_SETTINGS();
+
+    std::string GetFilename() const { return m_filename; }
+
+    SETTINGS_LOC GetLocation() const { return m_location; }
+
+    void SetLegacyFilename( const std::string& aFilename ) { m_legacy_filename = aFilename; }
+
+    /**
+     * Updates the parameters of this object based on the current JSON document contents
+     */
+    virtual void Load();
+
+    /**
+     * Stores the current parameters into the JSON document represented by this object
+     * Note: this doesn't do any writing to disk; that's handled by SETTINGS_MANAGER
+     */
+    virtual void Store();
+
+    /**
+     * Loads the backing file from disk and then calls Load()
+     * @param aDirectory is the path to the file
+     */
+    virtual void LoadFromFile( const std::string& aDirectory );
+
+    /**
+     * Calls Store() and then writes the contents of the JSON document to a file
+     * @param aDirectory is the directory to save to, including trailing separator
+     */
+    virtual void SaveToFile( const std::string& aDirectory );
+
+    /**
+     * Resets all parameters to default values.  Does NOT write to file or update underlying JSON.
+     */
+    void ResetToDefaults();
+
+    /**
+     * Fetches a JSON object that is a subset of this JSON_SETTINGS object, using a path of the
+     * form "key1.key2.key3" to refer to nested objects.
+     * @param aPath is a string containing one or more keys separated by '.'
+     * @return a JSON object from within this one
+     */
+    nlohmann::json GetJson( std::string aPath ) const;
+
+    /**
+     * Fetches a value from within the JSON document.
+     * Will throw an exception if the value is not found or a mismatching type.
+     * @tparam ValueType is the type to cast to
+     * @param aPath is the path within the document to retrieve
+     * @return a value from within this document
+     */
+    template<typename ValueType>
+    ValueType Get( std::string aPath ) const
+    {
+        return GetJson( std::move( aPath ) ).get<ValueType>();
+    }
+
+    /**
+     * Stores a value into the JSON document
+     * Will throw an exception if ValueType isn't something that the library can handle
+     * @tparam ValueType is the type to store
+     * @param aPath is a path to store in the form "key1.key2.key3"
+     * @param aVal is the value to store
+     */
+    template<typename ValueType>
+    void Set( std::string aPath, ValueType aVal )
+    {
+        ( *this )[PointerFromString( std::move( aPath ) ) ] = aVal;
+    }
+
+    /**
+     * Migrates the schema of this settings from the version in the file to the latest version
+     *
+     * Schema migration doesn't need to be used every time a setting is added!  This is intended
+     * to be more of an "escape hatch" in the event that we decide to move settings around or make
+     * other changes to a settings file format that can't simply be handled by loading a new default
+     *
+     * @return true if migration was successful
+     */
+    virtual bool Migrate();
+
+    /**
+     * Migrates from wxConfig to JSON-based configuration.  Should be implemented by any subclasses
+     * of JSON_SETTINGS that map to a legacy (wxConfig-based) config file.
+     * @param aLegacyConfig is a wxConfigBase holding a loaded configuration to migrate
+     * @return true if migration was successful
+     */
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig );
+
+    /**
+     * Transfers ownership of a given NESTED_SETTINGS to this object.
+     * Can be used to construct a NESTED_SETTINGS without the parent object needing to know about
+     * the implementation of the nested object;
+     *
+     * @param aSettings is the settings object to take ownership of
+     * @param aTarget is a pointer to update to the passed in settings
+     */
+    void AddNestedSettings( NESTED_SETTINGS* aSettings );
+
+    /**
+    * 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 );
+
+protected:
+
+    /**
+    * Translates a legacy wxConfig value to a given JSON pointer value
+    * @tparam ValueType is the basic type of the value
+    * @param aConfig is the legacy config to read from
+    * @param aKey is the key (within the current path) to read
+    * @param aDest is a string that will form a JSON pointer (key1.key2.key3) to write to
+    */
+    template<typename ValueType>
+    bool fromLegacy( wxConfigBase* aConfig, const std::string& aKey, const std::string& aDest );
+
+    /**
+     * Translates a legacy wxConfig string value to a given JSON pointer value
+     * @param aConfig is the legacy config to read from
+     * @param aKey is the key (within the current path) to read
+     * @param aDest is a string that will form a JSON pointer (key1.key2.key3) to write to
+     */
+    bool fromLegacyString( wxConfigBase* aConfig, const std::string& aKey,
+                           const std::string& aDest );
+
+    /**
+    * Translates a legacy COLOR4D stored in a wxConfig string to a given JSON pointer value
+    * @param aConfig is the legacy config to read from
+    * @param aKey is the key (within the current path) to read
+    * @param aDest is a string that will form a JSON pointer (key1.key2.key3) to write to
+    */
+    bool fromLegacyColor( wxConfigBase* aConfig, const std::string& aKey,
+                          const std::string& aDest );
+
+    /// The filename (not including path) of this settings file
+    std::string m_filename;
+
+    /// The filename of the wxConfig legacy file (if different from m_filename)
+    std::string m_legacy_filename;
+
+    /// The location of this settings file (@see SETTINGS_LOC)
+    SETTINGS_LOC m_location;
+
+    /// The list of parameters (owned by this object)
+    std::vector<PARAM_BASE*> m_params;
+
+    /// Nested settings files that live inside this one, if any
+    std::vector<NESTED_SETTINGS*> m_nested_settings;
+
+    /// Whether or not the backing store file should be created it if doesn't exist
+    bool m_createIfMissing;
+
+    /// Whether or not the backing store file should be written
+    bool m_writeFile;
+
+    /// Version of this settings schema.
+    int m_schemaVersion;
+
+    /// A list of JSON pointers that are preserved during a read-update-write to disk
+    std::vector<nlohmann::json::json_pointer> m_preserved_paths;
+};
+
+// Specializations to allow conversion between wxString and std::string via JSON_SETTINGS API
+
+template<> wxString JSON_SETTINGS::Get( std::string aPath ) const;
+
+template<> void JSON_SETTINGS::Set<wxString>( std::string aPath, wxString aVal );
+
+// Specializations to allow directly reading/writing wxStrings from JSON
+
+void to_json( nlohmann::json& aJson, const wxString& aString );
+
+void from_json( const nlohmann::json& aJson, wxString& aString );
+
+#endif
diff --git a/include/settings/nested_settings.h b/include/settings/nested_settings.h
new file mode 100644
index 0000000000..56aa8e1e39
--- /dev/null
+++ b/include/settings/nested_settings.h
@@ -0,0 +1,60 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 NESTED_SETTINGS_H_
+#define NESTED_SETTINGS_H_
+
+#include <settings/json_settings.h>
+
+
+/**
+ * NESTED_SETTINGS is a JSON_SETTINGS that lives inside a JSON_SETTINGS.
+ * Instead of being backed by a JSON file on disk, it loads and stores to its parent.
+ */
+class NESTED_SETTINGS : public JSON_SETTINGS
+{
+public:
+    NESTED_SETTINGS( const std::string& aName, int aSchemaVersion, JSON_SETTINGS* aParent,
+                     const std::string& aPath, nlohmann::json aDefault = nlohmann::json( {} ) );
+
+    virtual ~NESTED_SETTINGS() {}
+
+    /**
+     * Loads the JSON document from the parent and then calls Load()
+     * @param aDirectory
+     */
+    virtual void LoadFromFile( const std::string& aDirectory = "" ) override;
+
+    /**
+     * Calls Store() and then saves the JSON document contents into the parent JSON_SETTINGS
+     * @param aDirectory is ignored
+     */
+    virtual void SaveToFile( const std::string& aDirectory = "" ) override;
+
+private:
+
+    /// A pointer to the parent object to load and store from
+    JSON_SETTINGS* m_parent;
+
+    /// The path (in pointer format) of where to store this document in the parent
+    std::string m_path;
+};
+
+#endif
diff --git a/include/settings/parameters.h b/include/settings/parameters.h
new file mode 100644
index 0000000000..207586b9f5
--- /dev/null
+++ b/include/settings/parameters.h
@@ -0,0 +1,376 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 _PARAMETERS_H
+#define _PARAMETERS_H
+
+#include <string>
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <utility>
+#include <math/util.h>
+
+#include "json_settings.h"
+
+
+class PARAM_BASE
+{
+public:
+    PARAM_BASE( std::string aJsonPath, bool aReadOnly ) :
+            m_path( std::move( aJsonPath ) ), m_readOnly( aReadOnly ) {}
+
+    virtual ~PARAM_BASE() = default;
+
+    /**
+     * Loads the value of this parameter from JSON to the underlying storage
+     * @param aSettings is the JSON_SETTINGS object to load from.
+     */
+    virtual void Load( JSON_SETTINGS* aSettings ) const = 0;
+
+    /**
+     * Stores the value of this parameter to the given JSON_SETTINGS object
+     * @param aSettings is the JSON_SETTINGS object to store into.
+     */
+    virtual void Store( JSON_SETTINGS* aSettings ) const = 0;
+
+    virtual void SetDefault() = 0;
+
+protected:
+
+    std::string m_path;
+
+    ///! True if the parameter pointer should never be overwritten
+    bool m_readOnly;
+};
+
+template<typename ValueType>
+class PARAM : public PARAM_BASE
+{
+public:
+    PARAM( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault,
+           bool aReadOnly = false ) :
+            PARAM_BASE( aJsonPath, aReadOnly ), m_ptr( aPtr ), m_default( aDefault ),
+            m_min(), m_max(), m_use_minmax( false )
+    {}
+
+    PARAM( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault, ValueType aMin,
+            ValueType aMax, bool aReadOnly = false ) :
+            PARAM_BASE( aJsonPath, aReadOnly ), m_ptr( aPtr ), m_default( aDefault ),
+            m_min( aMin ), m_max( aMax ), m_use_minmax( true )
+    {}
+
+    void Load( JSON_SETTINGS* aSettings ) const override
+    {
+        if( m_readOnly )
+            return;
+
+        ValueType val = m_default;
+
+        try
+        {
+            val = aSettings->Get<ValueType>( m_path );
+
+            if( m_use_minmax )
+            {
+                if( val > m_max || val < m_min )
+                    val = m_default;
+            }
+        }
+        catch( ... )
+        {}
+
+        *m_ptr = val;
+    }
+
+    void Store( JSON_SETTINGS* aSettings) const override
+    {
+        aSettings->Set<ValueType>( m_path, *m_ptr );
+    }
+
+    ValueType GetDefault() const
+    {
+        return m_default;
+    }
+
+    virtual void SetDefault() override
+    {
+        *m_ptr = m_default;
+    }
+
+private:
+    ValueType* m_ptr;
+    ValueType m_default;
+    ValueType m_min;
+    ValueType m_max;
+    bool m_use_minmax;
+};
+
+/**
+ * Like a normal param, but with custom getter and setter functions
+ * @tparam ValueType is the value to store
+ */
+template<typename ValueType>
+class PARAM_LAMBDA : public PARAM_BASE
+{
+public:
+    PARAM_LAMBDA( const std::string& aJsonPath,  std::function<ValueType()> aGetter,
+            std::function<void( ValueType )> aSetter, ValueType aDefault, bool aReadOnly = false ) :
+            PARAM_BASE( aJsonPath, aReadOnly ), m_default( aDefault ),  m_getter( aGetter ),
+            m_setter( aSetter )
+    {}
+
+    void Load( JSON_SETTINGS* aSettings ) const override
+    {
+        if( m_readOnly )
+            return;
+
+        ValueType val = m_default;
+
+        try
+        {
+            val = aSettings->Get<ValueType>( m_path );
+        }
+        catch( ... )
+        {}
+
+        m_setter( val );
+    }
+
+    void Store( JSON_SETTINGS* aSettings) const override
+    {
+        aSettings->Set<ValueType>( m_path, m_getter() );
+    }
+
+    ValueType GetDefault() const
+    {
+        return m_default;
+    }
+
+    virtual void SetDefault() override
+    {
+        m_setter( m_default );
+    }
+
+private:
+    ValueType m_default;
+
+    std::function<ValueType()> m_getter;
+
+    std::function<void( ValueType )> m_setter;
+};
+
+/**
+ * Represents a parameter that has a scaling factor between the value in the file and the
+ * value used internally (i.e. the value pointer).  This basically only makes sense to use
+ * with int or double as ValueType.
+ * @tparam ValueType is the internal type: the file always stores a double.
+ */
+template<typename ValueType>
+class PARAM_SCALED: public PARAM_BASE
+{
+public:
+    PARAM_SCALED( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault,
+                  double aScale = 1.0, bool aReadOnly = false ) :
+            PARAM_BASE( aJsonPath, aReadOnly ), m_ptr( aPtr ), m_default( aDefault ),
+            m_min(), m_max(), m_use_minmax( false ), m_scale( aScale )
+    {}
+
+    PARAM_SCALED( const std::string& aJsonPath, ValueType* aPtr, ValueType aDefault, ValueType aMin,
+                  ValueType aMax, double aScale = 1.0, bool aReadOnly = false ) :
+            PARAM_BASE( aJsonPath, aReadOnly ), m_ptr( aPtr ), m_default( aDefault ),
+            m_min( aMin ), m_max( aMax ), m_use_minmax( true ), m_scale( aScale )
+    {}
+
+    void Load( JSON_SETTINGS* aSettings ) const override
+    {
+        if( m_readOnly )
+            return;
+
+        double dval = m_default * m_scale;
+
+        try
+        {
+            dval = aSettings->Get<double>( m_path );
+        }
+        catch( ... )
+        {}
+
+        ValueType val = KiROUND<ValueType>( dval / m_scale );
+
+        if( m_use_minmax )
+        {
+            if( val > m_max || val < m_min )
+                val = m_default;
+        }
+
+        *m_ptr = val;
+    }
+
+    void Store( JSON_SETTINGS* aSettings) const override
+    {
+        aSettings->Set<double>( m_path, *m_ptr * m_scale );
+    }
+
+    ValueType GetDefault() const
+    {
+        return m_default;
+    }
+
+    virtual void SetDefault() override
+    {
+        *m_ptr = m_default;
+    }
+
+private:
+    ValueType* m_ptr;
+    ValueType m_default;
+    ValueType m_min;
+    ValueType m_max;
+    bool m_use_minmax;
+    double m_scale;
+};
+
+template<typename Type>
+class PARAM_LIST : public PARAM_BASE
+{
+public:
+    PARAM_LIST( const std::string& aJsonPath, std::vector<Type>* aPtr,
+                std::initializer_list<Type> aDefault, bool aReadOnly = false ) :
+                PARAM_BASE( aJsonPath, aReadOnly ), m_ptr( aPtr ), m_default( aDefault ) {}
+
+    PARAM_LIST( const std::string& aJsonPath, std::vector<Type>* aPtr,
+                std::vector<Type> aDefault, bool aReadOnly = false ) :
+                PARAM_BASE( aJsonPath, aReadOnly ), m_ptr( aPtr ), m_default( aDefault ) {}
+
+    void Load( JSON_SETTINGS* aSettings ) const override
+    {
+        if( m_readOnly )
+            return;
+
+        std::vector<Type> val = m_default;
+
+        try
+        {
+            nlohmann::json js = aSettings->GetJson( m_path );
+
+            if( js.is_array() )
+            {
+                val.clear();
+
+                for( const auto& el : js.items() )
+                    val.push_back( el.value().get<Type>() );
+            }
+        }
+        catch( ... )
+        {
+        }
+
+        *m_ptr = val;
+    }
+
+    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 );
+    }
+
+    virtual void SetDefault() override
+    {
+        *m_ptr = m_default;
+    }
+
+private:
+    std::vector<Type>* m_ptr;
+
+    std::vector<Type> m_default;
+};
+
+/**
+ * Represents a map of <std::string, Value>.  The key parameter has to be a string in JSON.
+ *
+ * The key must be stored in UTF-8 format, so any translated strings or strings provided by the
+ * user as a key must be converted to UTF-8 at the site where they are placed in the underlying
+ * map that this PARAM_MAP points to.
+ *
+ * Values must also be in UTF-8, but if you use wxString as the value type, this conversion will
+ * be done automatically by the to_json and from_json helpers defined in json_settings.cpp
+ *
+ * @tparam Value is the value type of the map
+ */
+template<typename Value>
+class PARAM_MAP : public PARAM_BASE
+{
+public:
+    PARAM_MAP( const std::string& aJsonPath, std::map<std::string, Value>* aPtr,
+               std::initializer_list<std::pair<const std::string, Value>> aDefault,
+               bool aReadOnly = false ) :
+            PARAM_BASE( aJsonPath, aReadOnly ), m_ptr( aPtr ), m_default( aDefault ) {}
+
+    void Load( JSON_SETTINGS* aSettings ) const override
+    {
+        if( m_readOnly )
+            return;
+
+        std::map<std::string, Value> val = m_default;
+
+        try
+        {
+            nlohmann::json js = aSettings->GetJson( m_path );
+
+            if( js.is_object() )
+            {
+                val.clear();
+
+                for( const auto& el : js.items() )
+                    val[ el.key() ] = el.value().get<Value>();
+            }
+        }
+        catch( ... )
+        {
+        }
+
+        *m_ptr = val;
+    }
+
+    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
+    {
+        *m_ptr = m_default;
+    }
+
+private:
+    std::map<std::string, Value>* m_ptr;
+
+    std::map<std::string, Value> m_default;
+};
+
+#endif
diff --git a/include/settings/settings_manager.h b/include/settings/settings_manager.h
new file mode 100644
index 0000000000..f5fe53a7fa
--- /dev/null
+++ b/include/settings/settings_manager.h
@@ -0,0 +1,237 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 _SETTINGS_MANAGER_H
+#define _SETTINGS_MANAGER_H
+
+#include <settings/color_settings.h>
+#include <wx/wx.h>
+
+class COLOR_SETTINGS;
+class COMMON_SETTINGS;
+
+
+class SETTINGS_MANAGER
+{
+public:
+    SETTINGS_MANAGER();
+
+    ~SETTINGS_MANAGER();
+
+    /**
+     * @return true if settings load was successful
+     */
+    bool IsOK() { return m_ok; }
+
+    /**
+     * Takes ownership of the pointer passed in
+     * @param aSettings is a settings object to register
+     * @return a handle to the owned pointer
+     */
+    JSON_SETTINGS* RegisterSettings( JSON_SETTINGS* aSettings, bool aLoadNow = true );
+
+    void Load();
+
+    void Load( JSON_SETTINGS* aSettings );
+
+    void Save();
+
+    void Save( JSON_SETTINGS* aSettings );
+
+    /**
+     * If the given settings object is registered, save it to disk and unregister it
+     * @param aSettings is the object to release
+     */
+    void FlushAndRelease( JSON_SETTINGS* aSettings );
+
+    /**
+     * Returns a handle to the a given settings by type
+     * If the settings have already been loaded, returns the existing pointer.
+     * If the settings have not been loaded, creates a new object owned by the
+     * settings manager and returns a pointer to it.
+     *
+     * @tparam AppSettings is a type derived from APP_SETTINGS_BASE
+     * @param aLoadNow is true to load the registered file from disk immediately
+     * @return a pointer to a loaded settings object
+     */
+    template<typename AppSettings>
+    AppSettings* GetAppSettings( bool aLoadNow = true )
+    {
+        AppSettings* ret = nullptr;
+
+        auto it = std::find_if( m_settings.begin(), m_settings.end(),
+                                []( const std::unique_ptr<JSON_SETTINGS>& aSettings ) {
+                                    return dynamic_cast<AppSettings*>( aSettings.get() );
+                                } );
+
+        if( it != m_settings.end() )
+            ret = dynamic_cast<AppSettings*>( it->get() );
+        else
+            ret = static_cast<AppSettings*>( RegisterSettings( new AppSettings, aLoadNow ) );
+
+        return ret;
+    }
+
+    /**
+     * Retrieves a color settings object that applications can read colors from.
+     * If the given settings file cannot be found, returns the default settings.
+     *
+     * @param aName is the name of the color scheme to load
+     * @return a loaded COLOR_SETTINGS object
+     */
+    COLOR_SETTINGS* GetColorSettings( std::string aName = "default" );
+
+    /**
+     * Safely saves a COLOR_SETTINGS to disk, preserving any changes outside the given namespace.
+     *
+     * A color settings namespace is one of the top-level JSON objects like "board", etc.
+     * This will preform a read-modify-write
+     *
+     * @param aSettings is a pointer to a valid COLOR_SETTINGS object managed by SETTINGS_MANAGER
+     * @param aNamespace is the namespace of settings to save
+     */
+    void SaveColorSettings( COLOR_SETTINGS* aSettings, const std::string& aNamespace = "" );
+
+    /**
+     * Retrieves the common settings shared by all applications
+     * @return a pointer to a loaded COMMON_SETTINGS
+     */
+    COMMON_SETTINGS* GetCommonSettings() { return m_common_settings; }
+
+    /**
+     * Returns the path a given settings file should be loaded from / stored to.
+     * @param aSettings is the settings object
+     * @return a path based on aSettings->m_location
+     */
+    std::string GetPathForSettingsFile( JSON_SETTINGS* aSettings );
+
+    /**
+     * Handles the initialization of the user settings directory and migration from previous
+     * KiCad versions as needed.
+     *
+     * This method will check for the existence of the user settings path for this KiCad version.
+     * If it exists, settings load will proceed normally using that path.
+     *
+     * If that directory is empty or does not exist, the migration wizard will be launched, which
+     * will give users the option to migrate settings from a previous KiCad version (if one is
+     * found), manually specify a directory to migrate fromm, or start with default settings.
+     *
+     * @return true if migration was successful or not necessary, false otherwise
+     */
+    bool MigrateIfNeeded();
+
+    /**
+     * Helper for DIALOG_MIGRATE_SETTINGS to specify a source for migration
+     * @param aSource is a directory containing settings files to migrate from (can be empty)
+     */
+    void SetMigrationSource( const wxString& aSource ) { m_migration_source = aSource; }
+
+    /**
+     * Retreives the name of the most recent previous KiCad version that can be found in the
+     * user settings directory.  For legacy versions (5.x, and 5.99 builds before this code was
+     * written), this will return "5.x"
+     *
+     * @param aName is filled with the name of the previous version, if one exists
+     * @return true if a previous version to migrate from exists
+     */
+    bool GetPreviousVersionPaths( std::vector<wxString>* aName = nullptr );
+
+    /**
+     * Checks if a given path is probably a valid KiCad configuration directory.
+     * Actually it just checks if a file called "kicad_common" exists, because that's probably
+     * good enough for now.
+     *
+     * @param aPath is the path to check
+     * @return true if the path contains KiCad settings
+     */
+    static bool IsSettingsPathValid( const wxString& aPath );
+
+    /**
+     * Returns the path where color scheme files are stored
+     * (normally ./colors/ under the user settings path)
+     */
+    static std::string GetColorSettingsPath();
+
+    /**
+     * Return the user configuration path used to store KiCad's configuration files.
+     *
+     * @see calculateUserSettingsPath
+     *
+     * NOTE: The path is cached at startup, it will never change during program lifetime!
+     *
+     * @return A string containing the config path for Kicad
+     */
+    static std::string GetUserSettingsPath();
+
+    /**
+     * Parses the current KiCad build version and extracts the major and minor revision to use
+     * as the name of the settings directory for this KiCad version.
+     *
+     * @return a string such as "5.1"
+     */
+    static std::string GetSettingsVersion();
+
+private:
+
+    /**
+     * Determines the base path for user settings files.
+     *
+     * The configuration path order of precedence is determined by the following criteria:
+     *
+     * - The value of the KICAD_CONFIG_HOME environment variable
+     * - The value of the XDG_CONFIG_HOME environment variable.
+     * - The result of the call to wxStandardPaths::GetUserConfigDir() with ".config" appended
+     *   as required on Linux builds.
+     *
+     * @param aIncludeVer will append the current KiCad version if true (default)
+     * @param aUseEnv will prefer the base path found in the KICAD_CONFIG_DIR if found (default)
+     * @return A string containing the config path for Kicad
+     */
+    static std::string calculateUserSettingsPath( bool aIncludeVer = true, bool aUseEnv = true );
+
+    /**
+     * Compares two settings versions, like "5.99" and "6.0"
+     * @return -1 if aFirst is older than aSecond, 1 if aFirst is newer than aSecond, 0 otherwise
+     */
+    static int compareVersions( const std::string& aFirst, const std::string& aSecond );
+
+    /**
+     * Extracts the numeric version from a given settings string
+     * @param aVersionString is the string to split at the "."
+     * @param aMajor will store the first part
+     * @param aMinor will store the second part
+     * @return true if extraction succeeded
+     */
+    static bool extractVersion( const std::string& aVersionString, int* aMajor, int* aMinor );
+
+    std::vector<std::unique_ptr<JSON_SETTINGS>> m_settings;
+
+    std::unordered_map<std::string, COLOR_SETTINGS*> m_color_settings;
+
+    // Convenience shortcut
+    COMMON_SETTINGS* m_common_settings;
+
+    wxString m_migration_source;
+
+    /// True if settings loaded successfully at construction
+    bool m_ok;
+};
+
+#endif
diff --git a/include/tool/coroutine.h b/include/tool/coroutine.h
index 5f7f6a3a44..2fc124d819 100644
--- a/include/tool/coroutine.h
+++ b/include/tool/coroutine.h
@@ -34,9 +34,9 @@
 #include <valgrind/valgrind.h>
 #endif
 
-#include <advanced_config.h>
 #include <libcontext.h>
 #include <memory>
+#include <advanced_config.h>
 
 /**
  *  Class COROUNTINE.
diff --git a/include/tool/tool_base.h b/include/tool/tool_base.h
index 185fa2e2dd..c6fcf3a45e 100644
--- a/include/tool/tool_base.h
+++ b/include/tool/tool_base.h
@@ -30,7 +30,6 @@
 #include <base_struct.h>    // for KICAD_T
 
 #include <tool/tool_event.h>
-#include <tool/tool_settings.h>
 
 #include <functional>
 
@@ -145,7 +144,7 @@ public:
         return m_toolMgr;
     }
 
-    TOOL_SETTINGS& GetSettings();
+    //TOOL_SETTINGS& GetSettings();
 
     bool IsToolActive() const;
     
@@ -217,7 +216,7 @@ protected:
     ///> (eg. pcbnew.InteractiveSelection).
     std::string m_toolName;
     TOOL_MANAGER* m_toolMgr;
-    TOOL_SETTINGS m_toolSettings;
+    //TOOL_SETTINGS m_toolSettings;
 
 private:
     // hide the implementation to avoid spreading half of
diff --git a/include/tool/tool_settings.h b/include/tool/tool_settings.h
deleted file mode 100644
index 0da9f9582c..0000000000
--- a/include/tool/tool_settings.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2015 CERN
- * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
- *
- * 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 2
- * 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, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-
-#ifndef __TOOL_SETTINGS_H
-#define __TOOL_SETTINGS_H
-
-#include <core/settings.h>
-
-/**
- * TOOL_SETTINGS
- *
- * Manages persistent settings for a tool (just a simple wrapper to wxConfigBase)
- */
-class TOOL_BASE;
-
-class TOOL_SETTINGS : public SETTINGS
-{
-    public:
-        TOOL_SETTINGS( TOOL_BASE* aTool = NULL );
-        ~TOOL_SETTINGS();
-
-        template<class T>
-        T Get( const wxString& aName, T aDefaultValue ) const
-        {
-            wxConfigBase* config = getConfigBase();
-
-            if( !config )
-                return aDefaultValue;
-
-            T tmp = aDefaultValue;
-
-            config->Read( getKeyName( aName ), &tmp );
-            return tmp;
-        }
-
-        template<class T>
-        void Set( const wxString& aName, const T &aValue )
-        {
-            wxConfigBase* config = getConfigBase();
-
-            if( !config )
-                return;
-
-            config->Write( getKeyName( aName ), aValue );
-        }
-
-    private:
-        wxString getKeyName( const wxString& aEntryName ) const override;
-
-        ///> Returns pointer to currently used wxConfigBase. It might be NULL, if there is no
-        ///> TOOL_BASE assigned.
-        wxConfigBase* getConfigBase() const;
-
-        TOOL_BASE* m_tool;
-
-};
-
-#endif
diff --git a/include/ws_painter.h b/include/ws_painter.h
index 786380961b..121ff48293 100644
--- a/include/ws_painter.h
+++ b/include/ws_painter.h
@@ -50,6 +50,8 @@ public:
 
     WS_RENDER_SETTINGS();
 
+    void LoadColors( const COLOR_SETTINGS* aSettings ) override;
+
     /// @copydoc RENDER_SETTINGS::GetColor()
     virtual const COLOR4D& GetColor( const VIEW_ITEM* aItem, int aLayer ) const override;
 
diff --git a/include/ws_proxy_view_item.h b/include/ws_proxy_view_item.h
index 69a30ebb78..6f58eaa986 100644
--- a/include/ws_proxy_view_item.h
+++ b/include/ws_proxy_view_item.h
@@ -106,6 +106,15 @@ public:
         m_sheetCount = aSheetCount;
     }
 
+    /**
+     * Can be used to override which layer ID is used for worksheet item colors
+     * @param aLayerId is the color to use (will default to LAYER_WORKSHEET if this is not called)
+     */
+    void SetColorLayer( int aLayerId )
+    {
+        m_colorLayer = aLayerId;
+    }
+
     /// @copydoc VIEW_ITEM::ViewBBox()
     const BOX2I ViewBBox() const override;
 
@@ -150,6 +159,9 @@ protected:
 
     /// Sheets count number displayed in the title block.
     int m_sheetCount;
+
+    /// Layer that is used for worksheet color (LAYER_WORKSHEET is always used for visibility)
+    int m_colorLayer;
 };
 }
 
diff --git a/kicad/CMakeLists.txt b/kicad/CMakeLists.txt
index 9cb1f558bf..8c4cf2b0e3 100644
--- a/kicad/CMakeLists.txt
+++ b/kicad/CMakeLists.txt
@@ -20,6 +20,7 @@ set( KICAD_SRCS
     import_project.cpp
     kicad.cpp
     kicad_manager_frame.cpp
+    kicad_settings.cpp
     menubar.cpp
     project_template.cpp
     tree_project_frame.cpp
@@ -55,6 +56,10 @@ add_executable( kicad WIN32 MACOSX_BUNDLE
     ${KICAD_RESOURCES}
     )
 
+target_include_directories( kicad PRIVATE
+        $<TARGET_PROPERTY:nlohmann_json,INTERFACE_INCLUDE_DIRECTORIES>
+        )
+
 if( UNIX )
     # for build directory: create kiface symlinks so kicad (exe) can be run in-situ
     add_custom_target( kiface_sym_links
diff --git a/kicad/kicad.cpp b/kicad/kicad.cpp
index 011e9ba531..fe092ecba0 100644
--- a/kicad/kicad.cpp
+++ b/kicad/kicad.cpp
@@ -33,11 +33,10 @@
 #include <wx/stdpaths.h>
 #include <wx/string.h>
 
-#include <common.h>
 #include <filehistory.h>
 #include <hotkeys_basic.h>
 #include <kiway.h>
-#include <richio.h>
+#include <settings/settings_manager.h>
 #include <systemdirsappend.h>
 #include <wildcards_and_files_ext.h>
 
@@ -45,6 +44,7 @@
 
 #include "pgm_kicad.h"
 #include "kicad_manager_frame.h"
+#include "kicad_settings.h"
 
 
 // a dummy to quiet linking with EDA_BASE_FRAME::config();
@@ -90,6 +90,8 @@ bool PGM_KICAD::OnPgmInit()
     if( !InitPgm() )
         return false;
 
+    m_bm.InitSettings( new KICAD_SETTINGS );
+    GetSettingsManager().RegisterSettings( PgmSettings() );
     m_bm.Init();
 
     // Add search paths to feed the PGM_KICAD::SysSearch() function,
@@ -175,9 +177,13 @@ void PGM_KICAD::OnPgmExit()
 {
     Kiway.OnKiwayEnd();
 
-    SaveCommonSettings();
+    if( m_settings_manager && m_settings_manager->IsOK() )
+    {
+        SaveCommonSettings();
+        m_settings_manager->Save();
+    }
 
-    // write common settings to disk, and destroy everything in PGM_KICAD,
+    // Destroy everything in PGM_KICAD,
     // especially wxSingleInstanceCheckerImpl earlier than wxApp and earlier
     // than static destruction would.
     Destroy();
@@ -245,7 +251,13 @@ struct APP_KICAD : public wxApp
 
     bool OnInit()           override
     {
-        return program.OnPgmInit();
+        if( !program.OnPgmInit() )
+        {
+            program.OnPgmExit();
+            return false;
+        }
+
+        return true;
     }
 
     int  OnExit()           override
diff --git a/kicad/kicad_manager_frame.cpp b/kicad/kicad_manager_frame.cpp
index a436bd33ce..7a5e392536 100644
--- a/kicad/kicad_manager_frame.cpp
+++ b/kicad/kicad_manager_frame.cpp
@@ -35,6 +35,7 @@
 #include <kiway_express.h>
 #include <kiway_player.h>
 #include <panel_hotkeys_editor.h>
+#include <settings/common_settings.h>
 #include <tool/action_toolbar.h>
 #include <tool/common_control.h>
 #include <tool/tool_manager.h>
@@ -48,10 +49,9 @@
 #endif
 
 #include "kicad_manager_frame.h"
+#include "kicad_settings.h"
 
 
-#define TREE_FRAME_WIDTH_ENTRY     wxT( "LeftWinWidth" )
-
 #define SEP()   wxFileName::GetPathSeparator()
 
 // Not really useful, provided to save/restore params in project config file,
@@ -183,9 +183,9 @@ KICAD_MANAGER_FRAME::~KICAD_MANAGER_FRAME()
 }
 
 
-wxConfigBase* KICAD_MANAGER_FRAME::config()
+APP_SETTINGS_BASE* KICAD_MANAGER_FRAME::config()
 {
-    wxConfigBase* ret = PgmTop().PgmSettings();
+    APP_SETTINGS_BASE* ret = PgmTop().PgmSettings();
     wxASSERT( ret );
     return ret;
 }
@@ -480,8 +480,7 @@ void KICAD_MANAGER_FRAME::ShowChangedLanguage()
 
 void KICAD_MANAGER_FRAME::CommonSettingsChanged( bool aEnvVarsChanged )
 {
-    int historySize;
-    Pgm().CommonSettings()->Read( FILE_HISTORY_SIZE_KEY, &historySize, DEFAULT_FILE_HISTORY_SIZE );
+    int historySize = Pgm().GetCommonSettings()->m_System.file_history_size;
     PgmTop().GetFileHistory().SetMaxFiles( (unsigned) std::max( 0, historySize ) );
 }
 
@@ -492,17 +491,21 @@ void KICAD_MANAGER_FRAME::ClearMsg()
 }
 
 
-void KICAD_MANAGER_FRAME::LoadSettings( wxConfigBase* aCfg )
+void KICAD_MANAGER_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_BASE_FRAME::LoadSettings( aCfg );
-    aCfg->Read( TREE_FRAME_WIDTH_ENTRY, &m_leftWinWidth );
+
+    auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
+    m_leftWinWidth = settings->m_LeftWinWidth;
 }
 
 
-void KICAD_MANAGER_FRAME::SaveSettings( wxConfigBase* aCfg )
+void KICAD_MANAGER_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_BASE_FRAME::SaveSettings( aCfg );
-    aCfg->Write( TREE_FRAME_WIDTH_ENTRY, m_leftWin->GetSize().x );
+
+    auto settings = dynamic_cast<KICAD_SETTINGS*>( aCfg );
+    settings->m_LeftWinWidth = m_leftWin->GetSize().x;
 }
 
 
diff --git a/kicad/kicad_manager_frame.h b/kicad/kicad_manager_frame.h
index 2ae6726feb..3b1b398dc4 100644
--- a/kicad/kicad_manager_frame.h
+++ b/kicad/kicad_manager_frame.h
@@ -33,6 +33,7 @@
 class TREEPROJECTFILES;
 class TREE_PROJECT_FRAME;
 class ACTION_TOOLBAR;
+class KICAD_SETTINGS;
 
 // Identify the type of files handled by Kicad manager
 //
@@ -132,9 +133,9 @@ public:
     void LoadProject( const wxFileName& aProjectFileName );
 
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
 
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     void ShowChangedLanguage() override;
     void CommonSettingsChanged( bool aEnvVarsChanged ) override;
@@ -162,7 +163,7 @@ public:
     DECLARE_EVENT_TABLE()
 
 private:
-    wxConfigBase* config() override;
+    APP_SETTINGS_BASE* config() override;
 
     const SEARCH_STACK& sys_search() override;
 
diff --git a/kicad/kicad_settings.cpp b/kicad/kicad_settings.cpp
new file mode 100644
index 0000000000..7865cb552a
--- /dev/null
+++ b/kicad/kicad_settings.cpp
@@ -0,0 +1,42 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 <settings/parameters.h>
+#include "kicad_settings.h"
+
+
+///! Update the schema version whenever a migration is required
+const int kicadSchemaVersion = 0;
+
+
+KICAD_SETTINGS::KICAD_SETTINGS() : APP_SETTINGS_BASE( "kicad", kicadSchemaVersion )
+{
+    m_params.emplace_back( new PARAM<int>( "appearance.left_frame_width", &m_LeftWinWidth, 200 ) );
+}
+
+
+bool KICAD_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacy<int>( aCfg, "LeftWinWidth", "appearance.left_frame_width" );
+
+    return ret;
+}
diff --git a/kicad/kicad_settings.h b/kicad/kicad_settings.h
new file mode 100644
index 0000000000..271c309ef3
--- /dev/null
+++ b/kicad/kicad_settings.h
@@ -0,0 +1,44 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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_SETTINGS_H
+#define _KICAD_SETTINGS_H
+
+#include <settings/app_settings.h>
+
+
+class KICAD_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+
+    KICAD_SETTINGS();
+
+    virtual ~KICAD_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    int m_LeftWinWidth;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "KicadFrame"; }
+};
+
+#endif
diff --git a/kicad/pgm_kicad.h b/kicad/pgm_kicad.h
index 8eabba5635..6a3f8a3ebd 100644
--- a/kicad/pgm_kicad.h
+++ b/kicad/pgm_kicad.h
@@ -25,10 +25,9 @@
 #ifndef PGM_KICAD_H_
 #define PGM_KICAD_H_
 
-
 #include <pgm_base.h>
 #include <bin_mod.h>
-
+#include "kicad_settings.h"
 
 /**
  * PGM_KICAD
@@ -54,13 +53,13 @@ public:
 
     void MacOpenFile( const wxString& aFileName ) override;
 
-    FILE_HISTORY&   GetFileHistory()            { return *m_bm.m_history; }
+    FILE_HISTORY&      GetFileHistory()    { return *m_bm.m_history; }
 
-    wxConfigBase*   PgmSettings()               { return m_bm.m_config.get(); }
+    APP_SETTINGS_BASE* PgmSettings()       { return m_bm.m_config; }
 
-    SEARCH_STACK&   SysSearch()                 { return m_bm.m_search; }
+    SEARCH_STACK&      SysSearch()         { return m_bm.m_search; }
 
-    wxString        GetHelpFileName()           { return m_bm.m_help_file; }
+    wxString           GetHelpFileName()   { return m_bm.m_help_file; }
 
     // The PGM_* classes can have difficulties at termination if they
     // are not destroyed soon enough.  Relying on a static destructor can be
diff --git a/pagelayout_editor/CMakeLists.txt b/pagelayout_editor/CMakeLists.txt
index 5162120296..79b3b9d7a0 100644
--- a/pagelayout_editor/CMakeLists.txt
+++ b/pagelayout_editor/CMakeLists.txt
@@ -23,6 +23,7 @@ set( PL_EDITOR_SRCS
     pl_editor_layout.cpp
     files.cpp
     pl_editor_frame.cpp
+    pl_editor_settings.cpp
     pl_draw_panel_gal.cpp
     pl_editor_undo_redo.cpp
     properties_frame.cpp
diff --git a/pagelayout_editor/pl_draw_panel_gal.cpp b/pagelayout_editor/pl_draw_panel_gal.cpp
index bda0019387..ed305e283f 100644
--- a/pagelayout_editor/pl_draw_panel_gal.cpp
+++ b/pagelayout_editor/pl_draw_panel_gal.cpp
@@ -25,8 +25,9 @@
 #include <ws_proxy_view_item.h>
 #include <ws_data_model.h>
 #include <ws_painter.h>
-#include <colors_design_settings.h>
+#include <pgm_base.h>
 #include <pl_editor_frame.h>
+#include <settings/settings_manager.h>
 #include <gal/graphics_abstraction_layer.h>
 
 #include <functional>
@@ -47,6 +48,7 @@ PL_DRAW_PANEL_GAL::PL_DRAW_PANEL_GAL( wxWindow* aParentWindow, wxWindowID aWindo
     GetGAL()->SetWorldUnitLength( 1.0/IU_PER_MM /* 10 nm */ / 25.4 /* 1 inch in mm */ );
 
     m_painter = std::make_unique<KIGFX::WS_PAINTER>( m_gal );
+    m_painter->GetSettings()->LoadColors( Pgm().GetSettingsManager().GetColorSettings() );
     m_view->SetPainter( m_painter.get() );
     m_view->SetScaleLimits( 20.0, 0.05 );    // This fixes the zoom in and zoom out limits
 
diff --git a/pagelayout_editor/pl_editor.cpp b/pagelayout_editor/pl_editor.cpp
index d8b900eb89..18a6ccf2d7 100644
--- a/pagelayout_editor/pl_editor.cpp
+++ b/pagelayout_editor/pl_editor.cpp
@@ -27,15 +27,16 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
+#include <wx/file.h>
+#include <wx/snglinst.h>
+
 #include <kiface_i.h>
 #include <confirm.h>
 #include <gestfich.h>
-#include <ws_draw_item.h>
+#include <pgm_base.h>
 #include <pl_editor_frame.h>
-#include <build_version.h>
-#include <wx/file.h>
-#include <wx/snglinst.h>
+#include <pl_editor_settings.h>
+#include <settings/settings_manager.h>
 
 
 namespace PGE {
@@ -125,6 +126,8 @@ PGM_BASE& Pgm()
 
 bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
 {
+    InitSettings( new PL_EDITOR_SETTINGS );
+    aProgram->GetSettingsManager().RegisterSettings( KifaceSettings() );
     start_common( aCtlBits );
     return true;
 }
diff --git a/pagelayout_editor/pl_editor_frame.cpp b/pagelayout_editor/pl_editor_frame.cpp
index 58e492ca6b..79dc97c999 100644
--- a/pagelayout_editor/pl_editor_frame.cpp
+++ b/pagelayout_editor/pl_editor_frame.cpp
@@ -31,6 +31,7 @@
 #include <bitmaps.h>
 #include <pl_editor_frame.h>
 #include <pl_editor_id.h>
+#include <pl_editor_settings.h>
 #include <pl_draw_panel_gal.h>
 #include <pl_editor_screen.h>
 #include <ws_data_model.h>
@@ -298,8 +299,6 @@ void PL_EDITOR_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
     // do not show the window because we do not want any paint event
     Show( false );
 
-    wxConfigSaveSetups( Kiface().KifaceSettings(), m_configSettings );
-
     // On Linux, m_propertiesPagelayout must be destroyed
     // before deleting the main frame to avoid a crash when closing
     m_propertiesPagelayout->Destroy();
@@ -412,56 +411,41 @@ void PL_EDITOR_FRAME::InstallPreferences( PAGED_DIALOG* aParent,
 }
 
 
-static const wxChar propertiesFrameWidthKey[] = wxT( "PropertiesFrameWidth" );
-static const wxChar cornerOriginChoiceKey[] = wxT( "CornerOriginChoice" );
-static const wxChar blackBgColorKey[] = wxT( "BlackBgColor" );
-static const wxChar lastUsedPaperSizeKey[] = wxT( "LastUsedPaperSize" );
-static const wxChar lastUsedCustomWidthKey[] = wxT( "LastUsedCustomWidth" );
-static const wxChar lastUsedCustomHeightKey[] = wxT( "LastUsedCustomHeight" );
-static const wxChar lastUsedPortraitKey[] = wxT( "LastUsedWasPortrait" );
-
-
-void PL_EDITOR_FRAME::LoadSettings( wxConfigBase* aCfg )
+void PL_EDITOR_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_DRAW_FRAME::LoadSettings( aCfg );
 
-    aCfg->Read( propertiesFrameWidthKey, &m_propertiesFrameWidth, 150 );
-    aCfg->Read( cornerOriginChoiceKey, &m_originSelectChoice );
+    auto cfg = static_cast<PL_EDITOR_SETTINGS*>( aCfg );
 
-    bool flag;
-    aCfg->Read( blackBgColorKey, &flag, false );
-    SetDrawBgColor( flag ? BLACK : WHITE );
+    m_propertiesFrameWidth = cfg->m_PropertiesFrameWidth;
+    m_originSelectChoice = cfg->m_CornerOrigin;
 
-    int i;
-    aCfg->Read( lastUsedCustomWidthKey, &i, 17000 );
-    PAGE_INFO::SetCustomWidthMils( i );
-    aCfg->Read( lastUsedCustomHeightKey, &i, 11000 );
-    PAGE_INFO::SetCustomHeightMils( i );
+    SetDrawBgColor( cfg->m_BlackBackground ? BLACK : WHITE );
+
+    PAGE_INFO::SetCustomWidthMils( cfg->m_LastCustomWidth );
+    PAGE_INFO::SetCustomHeightMils( cfg->m_LastCustomHeight );
 
     PAGE_INFO pageInfo = GetPageSettings();
-    wxString msg;
-    aCfg->Read( lastUsedPaperSizeKey, &msg, "A3" );
-    aCfg->Read( lastUsedPortraitKey, &flag, false );
-    pageInfo.SetType( msg, flag );
+    pageInfo.SetType( cfg->m_LastPaperSize, cfg->m_LastWasPortrait );
     SetPageSettings( pageInfo );
 }
 
 
-void PL_EDITOR_FRAME::SaveSettings( wxConfigBase* aCfg )
+void PL_EDITOR_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_DRAW_FRAME::SaveSettings( aCfg );
 
+    auto cfg = static_cast<PL_EDITOR_SETTINGS*>( aCfg );
+
     m_propertiesFrameWidth = m_propertiesPagelayout->GetSize().x;
 
-    aCfg->Write( propertiesFrameWidthKey, m_propertiesFrameWidth);
-    aCfg->Write( cornerOriginChoiceKey, m_originSelectChoice );
-    aCfg->Write( blackBgColorKey, GetDrawBgColor() == BLACK );
-    aCfg->Write( lastUsedPaperSizeKey, GetPageSettings().GetType() );
-    aCfg->Write( lastUsedPortraitKey, GetPageSettings().IsPortrait() );
-    aCfg->Write( lastUsedCustomWidthKey, PAGE_INFO::GetCustomWidthMils() );
-    aCfg->Write( lastUsedCustomHeightKey, PAGE_INFO::GetCustomHeightMils() );
-
-    wxConfigSaveSetups( aCfg, GetConfigurationSettings() );
+    cfg->m_PropertiesFrameWidth = m_propertiesFrameWidth;
+    cfg->m_CornerOrigin         = m_originSelectChoice;
+    cfg->m_BlackBackground      = GetDrawBgColor() == BLACK;
+    cfg->m_LastPaperSize        = GetPageSettings().GetType();
+    cfg->m_LastWasPortrait      = GetPageSettings().IsPortrait();
+    cfg->m_LastCustomWidth      = PAGE_INFO::GetCustomWidthMils();
+    cfg->m_LastCustomHeight     = PAGE_INFO::GetCustomHeightMils();
 }
 
 
diff --git a/pagelayout_editor/pl_editor_frame.h b/pagelayout_editor/pl_editor_frame.h
index cd3c49e647..33c64e1bad 100644
--- a/pagelayout_editor/pl_editor_frame.h
+++ b/pagelayout_editor/pl_editor_frame.h
@@ -213,19 +213,9 @@ public:
 
     void InstallPreferences( PAGED_DIALOG* aParent, PANEL_HOTKEYS_EDITOR* aHotkeysPanel ) override;
 
-    /**
-     * Populates the applicatios settings list.
-     * (list of parameters that must be saved in project parameters)
-     * Currently, only the settings that are needed at start up by the main window are
-     * defined here.  There are other locally used settings scattered throughout the
-     * source code (mainly in dialogs).  If you need to define a configuration
-     * setting that need to be loaded at run time, this is the place to define it.
-     */
-    std::vector<PARAM_CFG*>& GetConfigurationSettings() { return m_configSettings; }
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     void OnSelectPage( wxCommandEvent& event );
 
diff --git a/pagelayout_editor/pl_editor_settings.cpp b/pagelayout_editor/pl_editor_settings.cpp
new file mode 100644
index 0000000000..208bd0d1fa
--- /dev/null
+++ b/pagelayout_editor/pl_editor_settings.cpp
@@ -0,0 +1,66 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#include <pl_editor_settings.h>
+#include <settings/parameters.h>
+#include <wx/config.h>
+
+
+///! Update the schema version whenever a migration is required
+const int plEditorSchemaVersion = 0;
+
+
+PL_EDITOR_SETTINGS::PL_EDITOR_SETTINGS() :
+        APP_SETTINGS_BASE( "pl_editor", plEditorSchemaVersion )
+{
+    m_params.emplace_back(
+            new PARAM<int>( "properties_frame_width", &m_PropertiesFrameWidth, 150 ) );
+
+    m_params.emplace_back( new PARAM<int>( "corner_origin", &m_CornerOrigin, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "black_background", &m_BlackBackground, false ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "last_paper_size", &m_LastPaperSize, "A3" ) );
+
+    m_params.emplace_back( new PARAM<int>( "last_custom_width", &m_LastCustomWidth, 17000 ) );
+
+    m_params.emplace_back( new PARAM<int>( "last_custom_height", &m_LastCustomHeight, 11000 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "last_was_portrait", &m_LastWasPortrait, false ) );
+}
+
+
+bool PL_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacy<int>(  aCfg, "PropertiesFrameWidth",  "properties_frame_width" );
+    ret &= fromLegacy<int>(  aCfg, "CornerOriginChoice",    "corner_origin" );
+    ret &= fromLegacy<bool>( aCfg, "BlackBgColor",          "black_background" );
+    ret &= fromLegacy<int>(  aCfg, "LastUsedPaperSize",     "last_paper_size" );
+    ret &= fromLegacy<int>(  aCfg, "LastUsedCustomWidth",   "last_custom_width" );
+    ret &= fromLegacy<int>(  aCfg, "LastUsedCustomHeight",  "last_custom_height" );
+    ret &= fromLegacy<bool>( aCfg, "LastUsedWasPortrait",   "last_was_portrait" );
+
+    return ret;
+}
diff --git a/pagelayout_editor/pl_editor_settings.h b/pagelayout_editor/pl_editor_settings.h
new file mode 100644
index 0000000000..5013f48920
--- /dev/null
+++ b/pagelayout_editor/pl_editor_settings.h
@@ -0,0 +1,59 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#ifndef _PL_EDITOR_SETTINGS_H
+#define _PL_EDITOR_SETTINGS_H
+
+#include <settings/app_settings.h>
+
+class PL_EDITOR_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+    PL_EDITOR_SETTINGS();
+
+    virtual ~PL_EDITOR_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    int m_CornerOrigin;
+
+    int m_PropertiesFrameWidth;
+
+    wxString m_LastPaperSize;
+
+    int m_LastCustomWidth;
+
+    int m_LastCustomHeight;
+
+    bool m_LastWasPortrait;
+
+    bool m_BlackBackground;
+
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "PlEditorFrame"; }
+};
+
+
+#endif
diff --git a/pcb_calculator/CMakeLists.txt b/pcb_calculator/CMakeLists.txt
index 8b9de76dbc..5fa93b0d2d 100644
--- a/pcb_calculator/CMakeLists.txt
+++ b/pcb_calculator/CMakeLists.txt
@@ -17,6 +17,7 @@ set( PCB_CALCULATOR_SRCS
     electrical_spacing_values.cpp
     params_read_write.cpp
     pcb_calculator_frame.cpp
+    pcb_calculator_settings.cpp
     datafile_read_write.cpp
     regulators_funct.cpp
     tracks_width_versus_current.cpp
diff --git a/pcb_calculator/attenuators/attenuator_classes.cpp b/pcb_calculator/attenuators/attenuator_classes.cpp
index 496c1c4676..3a4f964f92 100644
--- a/pcb_calculator/attenuators/attenuator_classes.cpp
+++ b/pcb_calculator/attenuators/attenuator_classes.cpp
@@ -9,12 +9,14 @@
 
 #include <attenuator_classes.h>
 #include <i18n_utility.h>
+#include <kiface_i.h>
+#include <pcb_calculator_settings.h>
 
 // Bitmaps:
-#include <att_pi.xpm>
-#include <att_tee.xpm>
 #include <att_bridge.xpm>
+#include <att_pi.xpm>
 #include <att_splitter.xpm>
+#include <att_tee.xpm>
 
 
 // Html texts showing the formulas
@@ -68,29 +70,27 @@ ATTENUATOR::~ATTENUATOR()
 }
 
 
-#define KEYWORD_ATTENUATOR_ATT  wxT( "Attenuation" )
-#define KEYWORD_ATTENUATOR_ZIN  wxT( "Zin" )
-#define KEYWORD_ATTENUATOR_ZOUT wxT( "Zout" )
-#define KEYWORD_ATTENUATORS     wxT( "Attenuators/" )
-
-void ATTENUATOR::ReadConfig( wxConfigBase* aConfig )
+void ATTENUATOR::ReadConfig()
 {
-    aConfig->SetPath( KEYWORD_ATTENUATORS + m_Name );
-    if( m_Attenuation_Enable )
-        aConfig->Read( KEYWORD_ATTENUATOR_ATT, &m_Attenuation, 6.0 );
-    aConfig->Read( KEYWORD_ATTENUATOR_ZIN, &m_Zin, 50.0 );
-    aConfig->Read( KEYWORD_ATTENUATOR_ZOUT, &m_Zout, 50.0 );
-    aConfig->SetPath( wxT( "../.." ) );
+    auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
+    std::string name = m_Name.ToStdString();
+
+    wxASSERT( cfg->m_Attenuators.attenuators.count( name ) );
+
+    m_Attenuation = cfg->m_Attenuators.attenuators.at( name ).attenuation;
+    m_Zin         = cfg->m_Attenuators.attenuators.at( name ).zin;
+    m_Zout        = cfg->m_Attenuators.attenuators.at( name ).zout;
 }
 
 
-void ATTENUATOR::WriteConfig( wxConfigBase* aConfig )
+void ATTENUATOR::WriteConfig()
 {
-    aConfig->SetPath( KEYWORD_ATTENUATORS + m_Name );
-    aConfig->Write( KEYWORD_ATTENUATOR_ATT, m_Attenuation );
-    aConfig->Write( KEYWORD_ATTENUATOR_ZIN, m_Zin );
-    aConfig->Write( KEYWORD_ATTENUATOR_ZOUT, m_Zout );
-    aConfig->SetPath( wxT( "../.." ) );
+    auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
+    std::string name = m_Name.ToStdString();
+
+    cfg->m_Attenuators.attenuators[ name ].attenuation = m_Attenuation;
+    cfg->m_Attenuators.attenuators[ name ].zin         = m_Zin;
+    cfg->m_Attenuators.attenuators[ name ].zout        = m_Zout;
 }
 
 
diff --git a/pcb_calculator/attenuators/attenuator_classes.h b/pcb_calculator/attenuators/attenuator_classes.h
index c3672155f7..f8078dcd89 100644
--- a/pcb_calculator/attenuators/attenuator_classes.h
+++ b/pcb_calculator/attenuators/attenuator_classes.h
@@ -12,7 +12,6 @@
 #ifndef ATTENUATORFUNC_H
 #define ATTENUATORFUNC_H
 
-#include <wx/config.h>
 #include <wx/bitmap.h>
 
 enum ATTENUATORS_TYPE {
@@ -62,16 +61,14 @@ public:
     /**
      * Function ReadConfig
      * Read values stored in config for this attenuator
-     * @param aConfig = the config to use
      */
-    void         ReadConfig( wxConfigBase* aConfig );
+    void         ReadConfig();
 
     /**
      * Function WriteConfig
      * Read values stored in config for this attenuator
-     * @param aConfig = the config to use
      */
-    void         WriteConfig( wxConfigBase* aConfig );
+    void         WriteConfig();
 };
 
 class ATTENUATOR_PI : public ATTENUATOR
diff --git a/pcb_calculator/board_classes_values.cpp b/pcb_calculator/board_classes_values.cpp
index bab8f58bee..6d33dbe2b7 100644
--- a/pcb_calculator/board_classes_values.cpp
+++ b/pcb_calculator/board_classes_values.cpp
@@ -19,7 +19,6 @@
  */
 
 #include <wx/app.h>
-#include <wx/config.h>
 #include <wx/msgdlg.h>
 
 #include <pcb_calculator_frame_base.h>
diff --git a/pcb_calculator/colorcode.cpp b/pcb_calculator/colorcode.cpp
index 09d74be414..9cb365bbca 100644
--- a/pcb_calculator/colorcode.cpp
+++ b/pcb_calculator/colorcode.cpp
@@ -19,7 +19,6 @@
  */
 
 #include <wx/app.h>
-#include <wx/config.h>
 #include <wx/msgdlg.h>
 
 #include <pcb_calculator_frame_base.h>
diff --git a/pcb_calculator/electrical_spacing_values.cpp b/pcb_calculator/electrical_spacing_values.cpp
index 6725953c91..9a3a8f3be6 100644
--- a/pcb_calculator/electrical_spacing_values.cpp
+++ b/pcb_calculator/electrical_spacing_values.cpp
@@ -23,7 +23,6 @@
  */
 
 #include <wx/app.h>
-#include <wx/config.h>
 
 #include <pcb_calculator_frame_base.h>
 #include <pcb_calculator.h>
diff --git a/pcb_calculator/params_read_write.cpp b/pcb_calculator/params_read_write.cpp
index da7119d6a8..e1f0f5585a 100644
--- a/pcb_calculator/params_read_write.cpp
+++ b/pcb_calculator/params_read_write.cpp
@@ -19,7 +19,6 @@
  */
 
 #include <wx/app.h>
-#include <wx/config.h>
 #include <wx/msgdlg.h>
 #include <wx/log.h>
 
diff --git a/pcb_calculator/pcb_calculator.cpp b/pcb_calculator/pcb_calculator.cpp
index 548c9801c1..ad5fb9cf4c 100644
--- a/pcb_calculator/pcb_calculator.cpp
+++ b/pcb_calculator/pcb_calculator.cpp
@@ -22,11 +22,12 @@
 #include <kiface_i.h>
 #include <confirm.h>
 #include <gestfich.h>
+#include <settings/settings_manager.h>
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <pcb_calculator_frame_base.h>
+#include <pcb_calculator_settings.h>
 #include <pcb_calculator.h>
 
 #include <bitmaps.h>
@@ -103,6 +104,8 @@ PGM_BASE& Pgm()
 
 bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
 {
+    InitSettings( new PCB_CALCULATOR_SETTINGS );
+    aProgram->GetSettingsManager().RegisterSettings( KifaceSettings() );
     start_common( aCtlBits );
 
     return true;
diff --git a/pcb_calculator/pcb_calculator.h b/pcb_calculator/pcb_calculator.h
index 9db2f0e579..6ee32e1e92 100644
--- a/pcb_calculator/pcb_calculator.h
+++ b/pcb_calculator/pcb_calculator.h
@@ -82,8 +82,8 @@ private:
     void OnPaintAttenuatorPanel( wxPaintEvent& event ) override;
 
     // Config read-write, virtual from EDA_BASE_FRAME
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     // R/W data files:
     bool ReadDataFile();
@@ -107,13 +107,13 @@ private:
      * Function TW_Init
      * Read config and init dialog widgets values
      */
-    void TW_Init( wxConfigBase* aCfg );
+    void TW_Init();
 
     /**
      * Function TW_WriteConfig
      * Write Track width prameters in config
      */
-    void TW_WriteConfig( wxConfigBase* aCfg );
+    void TW_WriteConfig();
 
     /**
      * Function OnTWParametersChanged
@@ -185,13 +185,13 @@ private:
      * Function VS_Init
      * Read config and init dialog widgets values
      */
-    void VS_Init( wxConfigBase* aCfg );
+    void VS_Init();
 
     /**
      * Function VS_WriteConfig
      * Write Via Size prameters in config
      */
-    void VS_WriteConfig( wxConfigBase* aCfg );
+    void VS_WriteConfig();
 
     /**
      * Function OnViaCalculate
diff --git a/pcb_calculator/pcb_calculator_frame.cpp b/pcb_calculator/pcb_calculator_frame.cpp
index 3c6c7bd09d..e0f530603c 100644
--- a/pcb_calculator/pcb_calculator_frame.cpp
+++ b/pcb_calculator/pcb_calculator_frame.cpp
@@ -18,35 +18,15 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <pgm_base.h>
 #include <pcb_calculator.h>
+#include <pcb_calculator_settings.h>
 #include <UnitSelector.h>
 #include <bitmaps.h>
 #include <geometry/shape_poly_set.h>
 
 
-#define KEYWORD_FRAME_POSX                      wxT( "Pcb_calculator_Pos_x" )
-#define KEYWORD_FRAME_POSY                      wxT( "Pcb_calculator_Pos_y" )
-#define KEYWORD_FRAME_SIZEX                     wxT( "Pcb_calculator_Size_x" )
-#define KEYWORD_FRAME_SIZEY                     wxT( "Pcb_calculator_Size_y" )
-#define KEYWORD_TRANSLINE_SELECTION             wxT( "Transline_selection" )
-#define KEYWORD_PAGE_SELECTION                  wxT( "Page_selection" )
-#define KEYWORD_COLORCODE_SELECTION             wxT( "CC_selection" )
-#define KEYWORD_ATTENUATORS_SELECTION           wxT( "Att_selection" )
-#define KEYWORD_BRDCLASS_SELECTION              wxT( "BrdClass_selection" )
-#define KEYWORD_ELECTRICAL_SPACING_SELECTION    wxT( "ElectSpacing_selection" )
-#define KEYWORD_ELECTRICAL_SPACING_VOLTAGE      wxT( "ElectSpacing_voltage" )
-#define KEYWORD_REGUL_R1                        wxT( "RegulR1" )
-#define KEYWORD_REGUL_R2                        wxT( "RegulR2" )
-#define KEYWORD_REGUL_VREF                      wxT( "RegulVREF" )
-#define KEYWORD_REGUL_VOUT                      wxT( "RegulVOUT" )
-#define KEYWORD_REGUL_SELECTED                  wxT( "RegulName" )
-#define KEYWORD_REGUL_TYPE                      wxT( "RegulType" )
-#define KEYWORD_REGUL_LAST_PARAM                wxT( "RegulLastParam" )
-#define KEYWORD_DATAFILE_FILENAME               wxT( "DataFilename" )
-
 // extension of pcb_calculator data filename:
 const wxString DataFileNameExt( wxT("pcbcalc") );
 
@@ -82,17 +62,15 @@ PCB_CALCULATOR_FRAME::PCB_CALCULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
     m_attenuator_list.push_back( new ATTENUATOR_SPLITTER() );
     m_currAttenuator = m_attenuator_list[0];
 
-    auto config = GetNewConfig( Pgm().App().GetAppName() );
-    LoadSettings( config.get() );
+    LoadSettings( config() );
 
     ReadDataFile();
 
     TranslineTypeSelection( m_currTransLineType );
     m_TranslineSelection->SetSelection( m_currTransLineType );
 
-    TW_Init( config.get() );
-
-    VS_Init( config.get() );
+    TW_Init();
+    VS_Init();
 
     SetAttenuator( m_AttenuatorsSelection->GetSelection() );
 
@@ -171,71 +149,58 @@ void PCB_CALCULATOR_FRAME::OnClosePcbCalc( wxCloseEvent& event )
 //    Destroy();
 }
 
-void PCB_CALCULATOR_FRAME::LoadSettings( wxConfigBase* aCfg )
+void PCB_CALCULATOR_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
     if( aCfg == NULL )
         return;
 
     EDA_BASE_FRAME::LoadSettings( aCfg );
 
-    long        ltmp;
-    wxString    msg;
-    aCfg->Read( KEYWORD_TRANSLINE_SELECTION, &ltmp, (long) DEFAULT_TYPE );
-    m_currTransLineType = (enum TRANSLINE_TYPE_ID) ltmp;
-    aCfg->Read( KEYWORD_PAGE_SELECTION, &ltmp, 0 );
-    m_Notebook->ChangeSelection( ltmp );
-    aCfg->Read( KEYWORD_COLORCODE_SELECTION, &ltmp, 1 );
-    m_rbToleranceSelection->SetSelection( ltmp );
-    aCfg->Read( KEYWORD_ATTENUATORS_SELECTION, &ltmp, 0 );
-    m_AttenuatorsSelection->SetSelection( ltmp );
-    aCfg->Read( KEYWORD_BRDCLASS_SELECTION, &ltmp, 0 );
-    m_BoardClassesUnitsSelector->SetSelection( ltmp );
+    auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( aCfg );
+
+    m_currTransLineType = static_cast<TRANSLINE_TYPE_ID>( cfg->m_TransLine.type );
+    m_Notebook->ChangeSelection( cfg->m_LastPage );
+    m_rbToleranceSelection->SetSelection( cfg->m_ColorCodeTolerance );
+    m_AttenuatorsSelection->SetSelection( cfg->m_Attenuators.type );
+    m_BoardClassesUnitsSelector->SetSelection( cfg->m_BoardClassUnits );
 
     // Regul panel config:
-    aCfg->Read( KEYWORD_REGUL_R1, &msg, wxT( "10" ) );
-    m_RegulR1Value->SetValue( msg );
-    aCfg->Read( KEYWORD_REGUL_R2, &msg, wxT( "10" ) );
-    m_RegulR2Value->SetValue( msg );
-    aCfg->Read( KEYWORD_REGUL_VREF, &msg, wxT( "3" ) );
-    m_RegulVrefValue->SetValue( msg );
-    aCfg->Read( KEYWORD_REGUL_VOUT, &msg, wxT( "12" ) );
-    m_RegulVoutValue->SetValue( msg );
-    aCfg->Read( KEYWORD_DATAFILE_FILENAME, &msg, wxT( "" ) );
-    SetDataFilename( msg );
-    aCfg->Read( KEYWORD_REGUL_SELECTED, &msg, wxT( "" ) );
-    m_lastSelectedRegulatorName = msg;
-    aCfg->Read( KEYWORD_REGUL_TYPE, &ltmp, 0 );
-    m_choiceRegType->SetSelection( ltmp );
-    aCfg->Read( KEYWORD_REGUL_LAST_PARAM, &ltmp, 0 );
-    wxRadioButton * regprms[3] =
-    {   m_rbRegulR1, m_rbRegulR2, m_rbRegulVout
-    };
-    if( (unsigned)ltmp >= 3 )
-        ltmp = 0;
+    m_RegulR1Value->SetValue( cfg->m_Regulators.r1 );
+    m_RegulR2Value->SetValue( cfg->m_Regulators.r2 );
+    m_RegulVrefValue->SetValue( cfg->m_Regulators.vref );
+    m_RegulVoutValue->SetValue( cfg->m_Regulators.vout );
+    SetDataFilename( cfg->m_Regulators.data_file );
+    m_lastSelectedRegulatorName = cfg->m_Regulators.selected_regulator;
+    m_choiceRegType->SetSelection( cfg->m_Regulators.type );
+
+    wxRadioButton* regprms[3] = { m_rbRegulR1, m_rbRegulR2, m_rbRegulVout };
+
+    if( cfg->m_Regulators.last_param >= 3 )
+        cfg->m_Regulators.last_param = 0;
+
     for( int ii = 0; ii < 3; ii++ )
-        regprms[ii]->SetValue( ltmp == ii );
+        regprms[ii]->SetValue( cfg->m_Regulators.last_param == ii );
 
     // Electrical panel config
-    aCfg->Read( KEYWORD_ELECTRICAL_SPACING_SELECTION, &ltmp, 0 );
-    m_ElectricalSpacingUnitsSelector->SetSelection( ltmp );
-    aCfg->Read( KEYWORD_ELECTRICAL_SPACING_VOLTAGE, &msg, wxT( "500" ) );
-    m_ElectricalSpacingVoltage->SetValue( msg );
+    m_ElectricalSpacingUnitsSelector->SetSelection( cfg->m_Electrical.spacing_units );
+    m_ElectricalSpacingVoltage->SetValue( cfg->m_Electrical.spacing_voltage );
 
-    for( unsigned ii = 0; ii < m_transline_list.size(); ii++ )
-        m_transline_list[ii]->ReadConfig( aCfg );
+    for( auto& transline : m_transline_list )
+        transline->ReadConfig();
 
-    for( unsigned ii = 0; ii < m_attenuator_list.size(); ii++ )
-        m_attenuator_list[ii]->ReadConfig( aCfg );
+    for( auto& attenuator : m_attenuator_list )
+        attenuator->ReadConfig();
 }
 
 
-void PCB_CALCULATOR_FRAME::SaveSettings( wxConfigBase* aCfg )
+void PCB_CALCULATOR_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     if( aCfg == NULL )
         return;
 
     EDA_BASE_FRAME::SaveSettings( aCfg );
 
+#if 0
     aCfg->Write( KEYWORD_TRANSLINE_SELECTION, (long) m_currTransLineType );
     aCfg->Write( KEYWORD_PAGE_SELECTION, m_Notebook->GetSelection() );
     aCfg->Write( KEYWORD_COLORCODE_SELECTION, m_rbToleranceSelection->GetSelection() );
@@ -267,16 +232,16 @@ void PCB_CALCULATOR_FRAME::SaveSettings( wxConfigBase* aCfg )
                      m_ElectricalSpacingUnitsSelector->GetSelection() );
     aCfg->Write( KEYWORD_ELECTRICAL_SPACING_VOLTAGE,
                      m_ElectricalSpacingVoltage->GetValue() );
+#endif
+    TW_WriteConfig();
 
-    TW_WriteConfig( aCfg );
-
-    VS_WriteConfig( aCfg );
+    VS_WriteConfig();
 
     for( unsigned ii = 0; ii < m_transline_list.size(); ii++ )
-        m_transline_list[ii]->WriteConfig( aCfg );
+        m_transline_list[ii]->WriteConfig();
 
     for( unsigned ii = 0; ii < m_attenuator_list.size(); ii++ )
-        m_attenuator_list[ii]->WriteConfig( aCfg );
+        m_attenuator_list[ii]->WriteConfig();
 }
 
 
diff --git a/pcb_calculator/pcb_calculator_settings.cpp b/pcb_calculator/pcb_calculator_settings.cpp
new file mode 100644
index 0000000000..9942172f14
--- /dev/null
+++ b/pcb_calculator/pcb_calculator_settings.cpp
@@ -0,0 +1,328 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#include <array>
+#include <pcb_calculator_settings.h>
+#include <settings/common_settings.h>
+#include <settings/parameters.h>
+#include <wx/config.h>
+
+
+///! Update the schema version whenever a migration is required
+const int pcbCalculatorSchemaVersion = 0;
+
+
+PCB_CALCULATOR_SETTINGS::PCB_CALCULATOR_SETTINGS() :
+        APP_SETTINGS_BASE( "pcb_calculator", pcbCalculatorSchemaVersion )
+{
+    m_params.emplace_back( new PARAM<int>( "board_class_units", &m_BoardClassUnits, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "color_code_tolerance", &m_ColorCodeTolerance, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "last_page", &m_LastPage, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "attenuators.type", &m_Attenuators.type, 0 ) );
+
+    const std::array<std::string, 4> att_names = { "att_pi", "att_tee",
+                                                   "att_bridge", "att_splitter" };
+
+    for( const auto& att_name : att_names )
+    {
+        std::string path = "attenuators." + att_name;
+        m_Attenuators.attenuators[ att_name ] = ATTENUATOR();
+        ATTENUATOR* att = &m_Attenuators.attenuators[ att_name ];
+
+        m_params.emplace_back( new PARAM<double>( path + ".attenuation", &att->attenuation, 6.0 ) );
+        m_params.emplace_back( new PARAM<double>( path + ".zin", &att->zin, 50.0 ) );
+        m_params.emplace_back( new PARAM<double>( path + ".zout", &att->zout, 50.0 ) );
+    }
+
+    m_params.emplace_back( new PARAM<int>( "electrical.spacing_units",
+            &m_Electrical.spacing_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "electrical.spacing_voltage",
+            &m_Electrical.spacing_voltage, "500" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "regulators.r1", &m_Regulators.r1, "10" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "regulators.r2", &m_Regulators.r2, "10" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "regulators.vref", &m_Regulators.vref, "3" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "regulators.vout", &m_Regulators.vout, "12" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "regulators.data_file",
+            &m_Regulators.data_file, "" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "regulators.selected_regulator",
+            &m_Regulators.selected_regulator, "" ) );
+
+    m_params.emplace_back( new PARAM<int>( "regulators.type", &m_Regulators.type, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "regulators.last_param", &m_Regulators.last_param, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "track_width.current",
+            &m_TrackWidth.current, "1.0" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "track_width.delta_tc",
+            &m_TrackWidth.delta_tc, "10.0" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "track_width.track_len",
+            &m_TrackWidth.track_len, "20" ) );
+
+    m_params.emplace_back( new PARAM<int>( "track_width.track_len_units",
+            &m_TrackWidth.track_len_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "track_width.resistivity",
+            &m_TrackWidth.resistivity, "1.72e-8" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "track_width.ext_track_width",
+            &m_TrackWidth.ext_track_width, "0.2" ) );
+
+    m_params.emplace_back( new PARAM<int>( "track_width.ext_track_width_units",
+            &m_TrackWidth.ext_track_width_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "track_width.ext_track_thickness",
+            &m_TrackWidth.ext_track_thickness, "0.035" ) );
+
+    m_params.emplace_back( new PARAM<int>( "track_width.ext_track_thickness_units",
+            &m_TrackWidth.ext_track_thickness_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "track_width.int_track_width",
+            &m_TrackWidth.int_track_width, "0.2" ) );
+
+    m_params.emplace_back( new PARAM<int>( "track_width.int_track_width_units",
+            &m_TrackWidth.int_track_width_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "track_width.int_track_thickness",
+            &m_TrackWidth.int_track_thickness, "0.035" ) );
+
+    m_params.emplace_back( new PARAM<int>( "track_width.int_track_thickness_units",
+            &m_TrackWidth.int_track_thickness_units, 0 ) );
+
+    {
+        const std::array<std::string, 8> transline_names = { "MicroStrip", "CoPlanar", "GrCoPlanar",
+                "RectWaveGuide", "Coax", "Coupled_MicroStrip", "StripLine", "TwistedPair" };
+
+        for( const auto& name : transline_names )
+        {
+            m_TransLine.param_values[ name ] = TL_PARAM_MAP();
+            m_TransLine.param_units[ name ] = TL_PARAM_UNITS_MAP();
+
+            std::string path = "trans_line." + name + ".";
+
+            m_params.emplace_back( new PARAM_MAP<double>( path + "values",
+                    &m_TransLine.param_values.at( name ), {} ) );
+
+            m_params.emplace_back( new PARAM_MAP<int>( path + "units",
+                    &m_TransLine.param_units.at( name ), {} ) );
+        }
+    }
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.hole_diameter",
+            &m_ViaSize.hole_diameter, "0.4" ) );
+
+    m_params.emplace_back( new PARAM<int>( "via_size.hole_diameter_units",
+            &m_ViaSize.hole_diameter_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.thickness",
+            &m_ViaSize.thickness, "0.035" ) );
+
+    m_params.emplace_back( new PARAM<int>( "via_size.thickness_units",
+            &m_ViaSize.thickness_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.length",
+            &m_ViaSize.length, "1.6" ) );
+
+    m_params.emplace_back( new PARAM<int>( "via_size.length_units", &m_ViaSize.length_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.pad_diameter",
+            &m_ViaSize.pad_diameter, "0.6" ) );
+
+    m_params.emplace_back( new PARAM<int>( "via_size.pad_diameter_units",
+            &m_ViaSize.pad_diameter_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.clearance_diameter",
+            &m_ViaSize.clearance_diameter, "1.0" ) );
+
+    m_params.emplace_back( new PARAM<int>( "via_size.clearance_diameter_units",
+            &m_ViaSize.clearance_diameter_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.characteristic_impedance",
+            &m_ViaSize.characteristic_impedance, "50" ) );
+
+    m_params.emplace_back( new PARAM<int>( "via_size.characteristic_impedance_units",
+            &m_ViaSize.characteristic_impedance_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.applied_current",
+            &m_ViaSize.applied_current, "1" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.plating_resistivity",
+            &m_ViaSize.plating_resistivity, "1.72e-8" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.permittivity",
+            &m_ViaSize.permittivity, "4.5" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.temp_rise",
+            &m_ViaSize.temp_rise, "10" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "via_size.pulse_rise_time",
+            &m_ViaSize.pulse_rise_time, "1" ) );
+}
+
+
+bool PCB_CALCULATOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacy<int>(  aCfg, "BrdClass_selection", "board_class_units" );
+    ret &= fromLegacy<int>(  aCfg, "CC_selection",       "color_code_tolerance" );
+    ret &= fromLegacy<int>(  aCfg, "Page_selection",     "last_page" );
+
+    ret &= fromLegacy<int>(  aCfg, "Att_selection",     "attenuators.type" );
+
+    {
+        nlohmann::json::json_pointer ptr = PointerFromString( "attenuators" );
+        const std::array<std::string, 4> att_names = { "att_pi", "att_tee",
+                                                       "att_bridge", "att_splitter" };
+        double val = 0;
+
+        for( const auto& att : att_names )
+        {
+            aCfg->SetPath( "Attenuators/" + att );
+            ptr.push_back( att );
+
+            if( aCfg->Read( "Attenuation", &val ) )
+                ( *this )[ptr]["attenuation"] = val;
+
+            if( aCfg->Read( "Zin", &val ) )
+                ( *this )[ptr]["zin"] = val;
+
+            if( aCfg->Read( "Zout", &val ) )
+                ( *this )[ptr]["zout"] = val;
+
+            ptr.pop_back();
+            aCfg->SetPath( "../.." );
+        }
+    }
+
+    ret &= fromLegacy<int>(   aCfg, "ElectSpacing_selection", "electrical.spacing_units" );
+    ret &= fromLegacyString(  aCfg, "ElectSpacing_voltage",   "electrical.spacing_voltage" );
+
+    ret &= fromLegacyString( aCfg, "RegulR1",           "regulators.r1" );
+    ret &= fromLegacyString( aCfg, "RegulR2",           "regulators.r2" );
+    ret &= fromLegacyString( aCfg, "RegulVREF",         "regulators.vref" );
+    ret &= fromLegacyString( aCfg, "RegulVOUT",         "regulators.vout" );
+    ret &= fromLegacyString( aCfg, "DataFilename",      "regulators.data_file" );
+    ret &= fromLegacyString( aCfg, "RegulName",         "regulators.selected_regulator" );
+    ret &= fromLegacy<int>(  aCfg, "RegulType",         "regulators.type" );
+    ret &= fromLegacy<int>(  aCfg, "RegulLastParam",    "regulators.last_param" );
+
+    ret &= fromLegacyString( aCfg, "TW_Track_Current",       "track_width.current" );
+    ret &= fromLegacyString( aCfg, "TW_Delta_TC",            "track_width.delta_tc" );
+    ret &= fromLegacyString( aCfg, "TW_Track_Len",           "track_width.track_len" );
+    ret &= fromLegacy<int>(  aCfg, "TW_Track_Len_Unit",      "track_width.track_len_units" );
+    ret &= fromLegacyString( aCfg, "TW_Resistivity",         "track_width.resistivity" );
+    ret &= fromLegacyString( aCfg, "TW_ExtTrack_Width",      "track_width.ext_track_width" );
+    ret &= fromLegacy<int>(  aCfg, "TW_ExtTrack_Width_Unit", "track_width.ext_track_width_units" );
+    ret &= fromLegacyString( aCfg, "TW_ExtTrack_Thickness",  "track_width.ext_track_thickness" );
+    ret &= fromLegacy<int>(  aCfg, "TW_ExtTrack_Thickness_Unit",
+        "track_width.ext_track_thickness_units" );
+    ret &= fromLegacyString( aCfg, "TW_IntTrack_Width",      "track_width.int_track_width" );
+    ret &= fromLegacy<int>(  aCfg, "TW_IntTrack_Width_Unit", "track_width.int_track_width_units" );
+    ret &= fromLegacyString( aCfg, "TW_IntTrack_Thickness",  "track_width.int_track_thickness" );
+    ret &= fromLegacy<int>(  aCfg, "TW_IntTrack_Thickness_Unit",
+            "track_width.int_track_thickness_units" );
+
+    ret &= fromLegacy<int>(  aCfg, "Transline_selection",    "trans_line.selection" );
+
+    {
+        nlohmann::json::json_pointer ptr = PointerFromString( "trans_line" );
+        wxString key;
+        double   value    = 0;
+        int      units    = 0;
+
+        const std::array<std::string, 8> transline_names = { "MicroStrip", "CoPlanar", "GrCoPlanar",
+                "RectWaveGuide", "Coax", "Coupled_MicroStrip", "StripLine", "TwistedPair" };
+
+        for( const auto& name : transline_names )
+        {
+            long index = 0;
+            aCfg->SetPath( name );
+            ptr.push_back( name );
+
+            while( aCfg->GetNextEntry( key, index ) )
+            {
+                // Keys look like "translineprmN" and "translineprmNunit"
+                wxString dest = key;
+                dest.Replace( "translineprm", wxEmptyString );
+
+                if( dest.EndsWith( "unit" ) )
+                {
+                    dest.Replace( "unit", wxEmptyString );
+                    aCfg->Read( key, &units );
+                    ptr.push_back( "units" );
+
+                    ( *this )[ptr].push_back( { { dest.ToStdString(), units } } );
+
+                    ptr.pop_back();
+                }
+                else
+                {
+                    aCfg->Read( key, &value );
+                    ptr.push_back( "values" );
+
+                    ( *this )[ptr].push_back( { { dest.ToStdString(), value } } );
+
+                    ptr.pop_back();
+                }
+            }
+
+            ptr.pop_back();
+            aCfg->SetPath( ".." );
+        }
+    }
+
+    ret &= fromLegacyString( aCfg, "VS_Hole_Dia",                 "via_size.hole_diameter" );
+    ret &= fromLegacy<int>(  aCfg, "VS_Hole_Dia_Unit",            "via_size.hole_diameter_units" );
+    ret &= fromLegacyString( aCfg, "VS_Plating_Thickness",        "via_size.thickness" );
+    ret &= fromLegacy<int>(  aCfg, "VS_Plating_Thickness_Unit",   "via_size.thickness_units" );
+    ret &= fromLegacyString( aCfg, "VS_Via_Length",               "via_size.length" );
+    ret &= fromLegacy<int>(  aCfg, "VS_Via_Length_Unit",          "via_size.length_units" );
+    ret &= fromLegacyString( aCfg, "VS_Pad_Dia",                  "via_size.pad_diameter" );
+    ret &= fromLegacy<int>(  aCfg, "VS_Pad_Dia_Unit",             "via_size.pad_diameter_units" );
+    ret &= fromLegacyString( aCfg, "VS_Clearance_Dia",            "via_size.clearance_diameter" );
+    ret &= fromLegacy<int>(  aCfg, "VS_Clearance_Dia_Unit",
+            "via_size.clearance_diameter_units" );
+    ret &= fromLegacyString( aCfg, "VS_Characteristic_Impedance",
+            "via_size.characteristic_impedance" );
+    ret &= fromLegacy<int>(  aCfg, "VS_Characteristic_Impedance_Unit",
+            "via_size.characteristic_impedance_units" );
+    ret &= fromLegacyString( aCfg, "VS_Current",                  "via_size.applied_current" );
+    ret &= fromLegacyString( aCfg, "VS_Resistivity",              "via_size.plating_resistivity" );
+    ret &= fromLegacyString( aCfg, "VS_Permittivity",             "via_size.permittivity" );
+    ret &= fromLegacyString( aCfg, "VS_Temperature_Differential", "via_size.temp_rise" );
+    ret &= fromLegacyString( aCfg, "VS_Pulse_Rise_Time",          "via_size.pulse_rise_time" );
+
+    return ret;
+}
diff --git a/pcb_calculator/pcb_calculator_settings.h b/pcb_calculator/pcb_calculator_settings.h
new file mode 100644
index 0000000000..1124b497f1
--- /dev/null
+++ b/pcb_calculator/pcb_calculator_settings.h
@@ -0,0 +1,148 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#ifndef _PCB_CALCULATOR_SETTINGS_H
+#define _PCB_CALCULATOR_SETTINGS_H
+
+#include <array>
+#include <settings/app_settings.h>
+
+class PCB_CALCULATOR_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+    struct ATTENUATOR
+    {
+        double attenuation;
+        double zin;
+        double zout;
+    };
+
+    struct ATTENUATORS
+    {
+        int type;
+        std::unordered_map<std::string, ATTENUATOR> attenuators;
+    };
+
+    struct ELECTRICAL
+    {
+        int spacing_units;
+        wxString spacing_voltage;
+    };
+
+    struct REGULATORS
+    {
+        wxString r1;
+        wxString r2;
+        wxString vref;
+        wxString vout;
+        wxString data_file;
+        wxString selected_regulator;
+        int type;
+        int last_param;
+    };
+
+    struct TRACK_WIDTH
+    {
+        wxString current;
+        wxString delta_tc;
+        wxString track_len;
+        int      track_len_units;
+        wxString resistivity;
+        wxString ext_track_width;
+        int      ext_track_width_units;
+        wxString ext_track_thickness;
+        int      ext_track_thickness_units;
+        wxString int_track_width;
+        int      int_track_width_units;
+        wxString int_track_thickness;
+        int      int_track_thickness_units;
+    };
+
+    /// Map of TRANSLINE_PRM id to value
+    typedef std::map<std::string, double> TL_PARAM_MAP;
+
+    /// Map of TRANSLINE_PRM id to units selection
+    typedef std::map<std::string, int> TL_PARAM_UNITS_MAP;
+
+    struct TRANSMISSION_LINE
+    {
+        int type;
+
+        /// Transline parameters, per transline type
+        std::map<std::string, TL_PARAM_MAP> param_values;
+
+        /// Transline parameter units selections, per transline type
+        std::map<std::string, TL_PARAM_UNITS_MAP> param_units;
+    };
+
+    struct VIA_SIZE
+    {
+        wxString hole_diameter;
+        int      hole_diameter_units;
+        wxString thickness;
+        int      thickness_units;
+        wxString length;
+        int      length_units;
+        wxString pad_diameter;
+        int      pad_diameter_units;
+        wxString clearance_diameter;
+        int      clearance_diameter_units;
+        wxString characteristic_impedance;
+        int      characteristic_impedance_units;
+        wxString applied_current;
+        wxString plating_resistivity;
+        wxString permittivity;
+        wxString temp_rise;
+        wxString pulse_rise_time;
+    };
+
+    PCB_CALCULATOR_SETTINGS();
+
+    virtual ~PCB_CALCULATOR_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    ATTENUATORS m_Attenuators;
+
+    int m_BoardClassUnits;
+
+    int m_ColorCodeTolerance;
+
+    ELECTRICAL m_Electrical;
+
+    int m_LastPage;
+
+    REGULATORS m_Regulators;
+
+    TRACK_WIDTH m_TrackWidth;
+
+    TRANSMISSION_LINE m_TransLine;
+
+    VIA_SIZE m_ViaSize;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "pcb_calculator"; }
+};
+
+#endif
diff --git a/pcb_calculator/regulators_funct.cpp b/pcb_calculator/regulators_funct.cpp
index f6c9add094..3642462709 100644
--- a/pcb_calculator/regulators_funct.cpp
+++ b/pcb_calculator/regulators_funct.cpp
@@ -21,7 +21,6 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <macros.h>
 #include <pcb_calculator.h>
diff --git a/pcb_calculator/tracks_width_versus_current.cpp b/pcb_calculator/tracks_width_versus_current.cpp
index e81e209cf2..ebe305f45c 100644
--- a/pcb_calculator/tracks_width_versus_current.cpp
+++ b/pcb_calculator/tracks_width_versus_current.cpp
@@ -27,51 +27,40 @@
 #include <cassert>
 #include <cmath>
 #include <wx/wx.h>
-#include <wx/config.h>
-#include <dialog_helpers.h>
+#include <kiface_i.h>
+#include <dialog_helpers.h>
 
 #include <pcb_calculator_frame_base.h>
 
 #include <pcb_calculator.h>
+#include <pcb_calculator_settings.h>
 #include <UnitSelector.h>
 #include <units_scales.h>
 
-wxString tracks_width_versus_current_formula =
-#include <tracks_width_versus_current_formula.h>
-
+wxString tracks_width_versus_current_formula =
+#include <tracks_width_versus_current_formula.h>
+
 extern double DoubleFromString( const wxString& TextValue );
 
-// Key words to read/write some parameters in config:
-#define KEYWORD_TW_CURRENT                     wxT( "TW_Track_Current" )
-#define KEYWORD_TW_DELTA_TC                    wxT( "TW_Delta_TC" )
-#define KEYWORD_TW_TRACK_LEN                   wxT( "TW_Track_Len" )
-#define KEYWORD_TW_TRACK_LEN_UNIT              wxT( "TW_Track_Len_Unit" )
-#define KEYWORD_TW_RESISTIVITY                 wxT( "TW_Resistivity" )
-#define KEYWORD_TW_EXTTRACK_WIDTH              wxT( "TW_ExtTrack_Width" )
-#define KEYWORD_TW_EXTTRACK_WIDTH_UNIT         wxT( "TW_ExtTrack_Width_Unit" )
-#define KEYWORD_TW_EXTTRACK_THICKNESS          wxT( "TW_ExtTrack_Thickness" )
-#define KEYWORD_TW_EXTTRACK_THICKNESS_UNIT     wxT( "TW_ExtTrack_Thickness_Unit" )
-#define KEYWORD_TW_INTTRACK_WIDTH              wxT( "TW_IntTrack_Width" )
-#define KEYWORD_TW_INTTRACK_WIDTH_UNIT         wxT( "TW_IntTrack_Width_Unit" )
-#define KEYWORD_TW_INTTRACK_THICKNESS          wxT( "TW_IntTrack_Thickness" )
-#define KEYWORD_TW_INTTRACK_THICKNESS_UNIT     wxT( "TW_IntTrack_Thickness_Unit" )
 
-void PCB_CALCULATOR_FRAME::TW_WriteConfig( wxConfigBase* aCfg )
+void PCB_CALCULATOR_FRAME::TW_WriteConfig()
 {
     // Save current parameters values in config.
-    aCfg->Write( KEYWORD_TW_CURRENT,                 m_TrackCurrentValue->GetValue() );
-    aCfg->Write( KEYWORD_TW_DELTA_TC,                m_TrackDeltaTValue->GetValue() );
-    aCfg->Write( KEYWORD_TW_TRACK_LEN,               m_TrackLengthValue->GetValue() );
-    aCfg->Write( KEYWORD_TW_TRACK_LEN_UNIT,          m_TW_CuLength_choiceUnit->GetSelection() );
-    aCfg->Write( KEYWORD_TW_RESISTIVITY,             m_TWResistivity->GetValue() );
-    aCfg->Write( KEYWORD_TW_EXTTRACK_WIDTH,          m_ExtTrackWidthValue->GetValue() );
-    aCfg->Write( KEYWORD_TW_EXTTRACK_WIDTH_UNIT,     m_TW_ExtTrackWidth_choiceUnit->GetSelection() );
-    aCfg->Write( KEYWORD_TW_EXTTRACK_THICKNESS,      m_ExtTrackThicknessValue->GetValue() );
-    aCfg->Write( KEYWORD_TW_EXTTRACK_THICKNESS_UNIT, m_ExtTrackThicknessUnit->GetSelection() );
-    aCfg->Write( KEYWORD_TW_INTTRACK_WIDTH,          m_IntTrackWidthValue->GetValue() );
-    aCfg->Write( KEYWORD_TW_INTTRACK_WIDTH_UNIT,     m_TW_IntTrackWidth_choiceUnit->GetSelection() );
-    aCfg->Write( KEYWORD_TW_INTTRACK_THICKNESS,      m_IntTrackThicknessValue->GetValue() );
-    aCfg->Write( KEYWORD_TW_INTTRACK_THICKNESS_UNIT, m_IntTrackThicknessUnit->GetSelection() );
+    auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
+
+    cfg->m_TrackWidth.current                   = m_TrackCurrentValue->GetValue();
+    cfg->m_TrackWidth.delta_tc                  = m_TrackDeltaTValue->GetValue();
+    cfg->m_TrackWidth.track_len                 = m_TrackLengthValue->GetValue();
+    cfg->m_TrackWidth.track_len_units           = m_TW_CuLength_choiceUnit->GetSelection();
+    cfg->m_TrackWidth.resistivity               = m_TWResistivity->GetValue();
+    cfg->m_TrackWidth.ext_track_width           = m_ExtTrackWidthValue->GetValue();
+    cfg->m_TrackWidth.ext_track_width_units     = m_TW_ExtTrackWidth_choiceUnit->GetSelection();
+    cfg->m_TrackWidth.ext_track_thickness       = m_ExtTrackThicknessValue->GetValue();
+    cfg->m_TrackWidth.ext_track_thickness_units = m_ExtTrackThicknessUnit->GetSelection();
+    cfg->m_TrackWidth.int_track_width           = m_IntTrackWidthValue->GetValue();
+    cfg->m_TrackWidth.int_track_width_units     = m_TW_IntTrackWidth_choiceUnit->GetSelection();
+    cfg->m_TrackWidth.int_track_thickness       = m_IntTrackThicknessValue->GetValue();
+    cfg->m_TrackWidth.int_track_thickness_units = m_IntTrackThicknessUnit->GetSelection();
 }
 
 
@@ -426,50 +415,38 @@ double PCB_CALCULATOR_FRAME::TWCalculateCurrent( double aWidth, double aThicknes
 }
 
 
-void PCB_CALCULATOR_FRAME::TW_Init( wxConfigBase* aCfg )
+void PCB_CALCULATOR_FRAME::TW_Init()
 {
-    int      tmp;
     wxString msg;
 
     // Disable calculations while we initialise.
     m_TWNested = true;
 
     // Read parameter values.
-    aCfg->Read( KEYWORD_TW_CURRENT,                 &msg, wxT( "1.0" ) );
-    m_TrackCurrentValue->SetValue( msg );
-    aCfg->Read( KEYWORD_TW_DELTA_TC,                &msg, wxT( "10.0" ) );
-    m_TrackDeltaTValue->SetValue( msg );
-    aCfg->Read( KEYWORD_TW_TRACK_LEN,               &msg, wxT( "20" ) );
-    m_TrackLengthValue->SetValue( msg );
-    aCfg->Read( KEYWORD_TW_TRACK_LEN_UNIT,          &tmp, 0 );
-    m_TW_CuLength_choiceUnit->SetSelection( tmp );
-    aCfg->Read( KEYWORD_TW_RESISTIVITY,             &msg, wxT( "1.72e-8" ) );
-    m_TWResistivity->SetValue( msg );
-    aCfg->Read( KEYWORD_TW_EXTTRACK_WIDTH,          &msg, wxT( "0.2" ) );
-    m_ExtTrackWidthValue->SetValue( msg );
-    aCfg->Read( KEYWORD_TW_EXTTRACK_WIDTH_UNIT,     &tmp, 0 );
-    m_TW_ExtTrackWidth_choiceUnit->SetSelection( tmp );
-    aCfg->Read( KEYWORD_TW_EXTTRACK_THICKNESS,      &msg, wxT( "0.035" ) );
-    m_ExtTrackThicknessValue->SetValue( msg );
-    aCfg->Read( KEYWORD_TW_EXTTRACK_THICKNESS_UNIT, &tmp, 0 );
-    m_ExtTrackThicknessUnit->SetSelection( tmp );
-    aCfg->Read( KEYWORD_TW_INTTRACK_WIDTH,          &msg, wxT( "0.2" ) );
-    m_IntTrackWidthValue->SetValue( msg );
-    aCfg->Read( KEYWORD_TW_INTTRACK_WIDTH_UNIT,     &tmp, 0 );
-    m_TW_IntTrackWidth_choiceUnit->SetSelection( tmp );
-    aCfg->Read( KEYWORD_TW_INTTRACK_THICKNESS,      &msg, wxT( "0.035" ) );
-    m_IntTrackThicknessValue->SetValue( msg );
-    aCfg->Read( KEYWORD_TW_INTTRACK_THICKNESS_UNIT, &tmp, 0 );
-    m_IntTrackThicknessUnit->SetSelection( tmp );
+    auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
+   
+    m_TrackCurrentValue->SetValue( cfg->m_TrackWidth.current );
+    m_TrackDeltaTValue->SetValue( cfg->m_TrackWidth.delta_tc );
+    m_TrackLengthValue->SetValue( cfg->m_TrackWidth.track_len );
+    m_TW_CuLength_choiceUnit->SetSelection( cfg->m_TrackWidth.track_len_units );
+    m_TWResistivity->SetValue( cfg->m_TrackWidth.resistivity );
+    m_ExtTrackWidthValue->SetValue( cfg->m_TrackWidth.ext_track_width );
+    m_TW_ExtTrackWidth_choiceUnit->SetSelection( cfg->m_TrackWidth.ext_track_width_units );
+    m_ExtTrackThicknessValue->SetValue( cfg->m_TrackWidth.ext_track_thickness );
+    m_ExtTrackThicknessUnit->SetSelection( cfg->m_TrackWidth.ext_track_thickness_units );
+    m_IntTrackWidthValue->SetValue( cfg->m_TrackWidth.int_track_width );
+    m_TW_IntTrackWidth_choiceUnit->SetSelection( cfg->m_TrackWidth.int_track_width_units );
+    m_IntTrackThicknessValue->SetValue( cfg->m_TrackWidth.int_track_thickness );
+    m_IntTrackThicknessUnit->SetSelection( cfg->m_TrackWidth.int_track_thickness_units );
 
-    if( tracks_width_versus_current_formula.StartsWith( "<!" ) )
-        m_htmlWinFormulas->SetPage( tracks_width_versus_current_formula );
-    else
-    {
-        wxString html_txt;
-        ConvertMarkdown2Html( wxGetTranslation( tracks_width_versus_current_formula ), html_txt );
-        m_htmlWinFormulas->SetPage( html_txt );
-    }
+    if( tracks_width_versus_current_formula.StartsWith( "<!" ) )
+        m_htmlWinFormulas->SetPage( tracks_width_versus_current_formula );
+    else
+    {
+        wxString html_txt;
+        ConvertMarkdown2Html( wxGetTranslation( tracks_width_versus_current_formula ), html_txt );
+        m_htmlWinFormulas->SetPage( html_txt );
+    }
 
     // Make sure the correct master mode is displayed.
     TWUpdateModeDisplay();
diff --git a/pcb_calculator/transline_dlg_funct.cpp b/pcb_calculator/transline_dlg_funct.cpp
index e58d0197e0..5bb7d9a249 100644
--- a/pcb_calculator/transline_dlg_funct.cpp
+++ b/pcb_calculator/transline_dlg_funct.cpp
@@ -18,7 +18,6 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <wx/wx.h>
-#include <wx/config.h>
 #include <wx/filename.h>
 
 #include <pcb_calculator_frame_base.h>
diff --git a/pcb_calculator/transline_ident.cpp b/pcb_calculator/transline_ident.cpp
index 149a4bbd68..764bb68bb2 100644
--- a/pcb_calculator/transline_ident.cpp
+++ b/pcb_calculator/transline_ident.cpp
@@ -45,8 +45,10 @@
 #include <stripline.h>
 #include <twistedpair.h>
 
-#include <transline_ident.h>
+#include <kiface_i.h>
+#include <pcb_calculator_settings.h>
 #include <UnitSelector.h>
+#include <transline_ident.h>
 
 
 /*
@@ -72,36 +74,6 @@ TRANSLINE_PRM::TRANSLINE_PRM( PRM_TYPE aType, PRMS_ID aId,
  }
 
 
-#define TRANSLINE_PRM_KEY wxT( "translineprm%d" )
-
-void TRANSLINE_PRM::ReadConfig( wxConfigBase* aConfig )
-{
-    if( m_Id == UNKNOWN_ID || m_Id == DUMMY_PRM )
-        return;
-
-    wxString key;
-    key.Printf( TRANSLINE_PRM_KEY, (int) m_Id );
-    aConfig->Read( key, &m_Value );
-
-    key += wxT( "unit" );
-    aConfig->Read( key, &m_UnitSelection );
-}
-
-
-void TRANSLINE_PRM::WriteConfig( wxConfigBase* aConfig )
-{
-    if( m_Id == UNKNOWN_ID || m_Id == DUMMY_PRM )
-        return;
-
-    wxString key;
-    key.Printf( TRANSLINE_PRM_KEY, (int) m_Id );
-    aConfig->Write( key, m_Value );
-
-    key += wxT( "unit" );
-    aConfig->Write( key, m_UnitSelection );
-}
-
-
 double TRANSLINE_PRM::ToUserUnit()
 {
     if( m_UnitCtrl && m_ConvUnit )
@@ -433,31 +405,49 @@ TRANSLINE_IDENT::~TRANSLINE_IDENT()
 {
     delete m_TLine;
     delete m_Icon;
-    for( unsigned ii = 0; ii < m_prms_List.size(); ii++ )
-        delete m_prms_List[ii];
+
+    for( auto& ii : m_prms_List )
+        delete ii;
 
     m_prms_List.clear();
 }
 
 
-void TRANSLINE_IDENT::ReadConfig( wxConfigBase* aConfig )
+void TRANSLINE_IDENT::ReadConfig()
 {
-    wxString text = wxString::FromUTF8( m_TLine->m_Name );
-    aConfig->SetPath( text );
-    for( unsigned ii = 0; ii < m_prms_List.size(); ii++ )
-        m_prms_List[ii]->ReadConfig( aConfig );
+    auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
+    std::string name( m_TLine->m_Name );
 
-    aConfig->SetPath( wxT( ".." ) );
+    if( cfg->m_TransLine.param_values.count( name ) )
+    {
+        wxASSERT( cfg->m_TransLine.param_units.count( name ) );
+
+        for( auto& param : m_prms_List )
+        {
+            std::string id = std::to_string( param->m_Id );
+
+            try
+            {
+                param->m_Value = cfg->m_TransLine.param_values.at( name ).at( id );
+                param->m_UnitSelection = cfg->m_TransLine.param_units.at( name ).at( id );
+            }
+            catch( ... )
+            {}
+        }
+    }
 }
 
 
-void TRANSLINE_IDENT::WriteConfig( wxConfigBase* aConfig )
+void TRANSLINE_IDENT::WriteConfig()
 {
-    wxString text = wxString::FromUTF8( m_TLine->m_Name );
-    aConfig->SetPath( text );
-    for( unsigned ii = 0; ii < m_prms_List.size(); ii++ )
-        m_prms_List[ii]->WriteConfig( aConfig );
+    auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
+    std::string name( m_TLine->m_Name );
 
-    aConfig->SetPath( wxT( ".." ) );
+    for( auto& param : m_prms_List )
+    {
+        std::string id = std::to_string( param->m_Id );
+        cfg->m_TransLine.param_values[ name ][ id ] = param->m_Value;
+        cfg->m_TransLine.param_units[ name ][ id ] = param->m_UnitSelection;
+    }
 }
 
diff --git a/pcb_calculator/transline_ident.h b/pcb_calculator/transline_ident.h
index 5aa924dd87..903d0472b1 100644
--- a/pcb_calculator/transline_ident.h
+++ b/pcb_calculator/transline_ident.h
@@ -26,7 +26,6 @@
 #define TRANSLINE_IDENT_H
 
 #include <vector>
-#include <wx/config.h>
 #include <wx/bitmap.h>
 
 #include <transline.h>
@@ -74,8 +73,6 @@ public: TRANSLINE_PRM( PRM_TYPE aType, PRMS_ID aId,
                        double aValue = 0.0,
                        bool aConvUnit = false );
 
-    void   ReadConfig( wxConfigBase* aConfig );
-    void   WriteConfig( wxConfigBase* aConfig );
     double ToUserUnit();
     double FromUserUnit();
 };
@@ -121,8 +118,8 @@ public:
     }
 
 
-    void ReadConfig( wxConfigBase* aConfig );
-    void WriteConfig( wxConfigBase* aConfig );
+    void ReadConfig();
+    void WriteConfig();
 };
 
 #endif      //  TRANSLINE_IDENT_H
diff --git a/pcb_calculator/via.cpp b/pcb_calculator/via.cpp
index fe7819447d..60022cd4a1 100644
--- a/pcb_calculator/via.cpp
+++ b/pcb_calculator/via.cpp
@@ -44,11 +44,10 @@
 
 #include <cmath>
 #include <wx/wx.h>
-#include <wx/config.h>
-
-#include <pcb_calculator_frame_base.h>
 
+#include <kiface_i.h>
 #include <pcb_calculator.h>
+#include <pcb_calculator_settings.h>
 #include <UnitSelector.h>
 #include <units_scales.h>
 
@@ -56,25 +55,6 @@
 
 extern double DoubleFromString( const wxString& TextValue );
 
-// Key words to read/write some parameters in config:
-#define KEYWORD_VS_HOLE_DIA           wxT( "VS_Hole_Dia" )
-#define KEYWORD_VS_HOLE_DIA_UNIT      wxT( "VS_Hole_Dia_Unit" )
-#define KEYWORD_VS_THICKNESS          wxT( "VS_Plating_Thickness" )
-#define KEYWORD_VS_THICKNESS_UNIT     wxT( "VS_Plating_Thickness_Unit" )
-#define KEYWORD_VS_LENGTH             wxT( "VS_Via_Length" )
-#define KEYWORD_VS_LENGTH_UNIT        wxT( "VS_Via_Length_Unit" )
-#define KEYWORD_VS_PAD_DIA            wxT( "VS_Pad_Dia" )
-#define KEYWORD_VS_PAD_DIA_UNIT       wxT( "VS_Pad_Dia_Unit" )
-#define KEYWORD_VS_CLEARANCE_DIA      wxT( "VS_Clearance_Dia" )
-#define KEYWORD_VS_CLEARANCE_DIA_UNIT wxT( "VS_Clearance_Dia_Unit" )
-#define KEYWORD_VS_CH_IMPEDANCE       wxT( "VS_Characteristic_Impedance" )
-#define KEYWORD_VS_CH_IMPEDANCE_UNIT  wxT( "VS_Characteristic_Impedance_Unit" )
-#define KEYWORD_VS_CURRENT            wxT( "VS_Current" )
-#define KEYWORD_VS_RESISTIVITY        wxT( "VS_Resistivity" )
-#define KEYWORD_VS_PERMITTIVITY       wxT( "VS_Permittivity" )
-#define KEYWORD_VS_TEMP_DIFF          wxT( "VS_Temperature_Differential" )
-#define KEYWORD_VS_PULSE_RISE_TIME    wxT( "VS_Pulse_Rise_Time" )
-
 /**
  * Shows a list of current relative dielectric constant(Er)
  * and set the selected value in main dialog frame
@@ -142,75 +122,56 @@ void PCB_CALCULATOR_FRAME::OnViaResetButtonClick( wxCommandEvent& event )
 }
 
 
-void PCB_CALCULATOR_FRAME::VS_Init( wxConfigBase* aCfg )
+void PCB_CALCULATOR_FRAME::VS_Init()
 {
-    int      tmp;
-    wxString msg;
+    auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
 
-    #define DEFAULT_UNIT_SEL_MM 0
-    // Read parameter values
-    aCfg->Read( KEYWORD_VS_HOLE_DIA,                &msg, wxT( "0.4" ) );
-    m_textCtrlHoleDia->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_HOLE_DIA_UNIT,           &tmp, DEFAULT_UNIT_SEL_MM );
-    m_choiceHoleDia->SetSelection( tmp );
+    m_textCtrlHoleDia->SetValue( cfg->m_ViaSize.hole_diameter );
+    m_choiceHoleDia->SetSelection( cfg->m_ViaSize.hole_diameter_units );
 
-    aCfg->Read( KEYWORD_VS_THICKNESS,               &msg, wxT( "0.035" ) );
-    m_textCtrlPlatingThickness->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_THICKNESS_UNIT,          &tmp, DEFAULT_UNIT_SEL_MM );
-    m_choicePlatingThickness->SetSelection( tmp );
+    m_textCtrlPlatingThickness->SetValue( cfg->m_ViaSize.thickness );
+    m_choicePlatingThickness->SetSelection( cfg->m_ViaSize.thickness_units );
 
-    aCfg->Read( KEYWORD_VS_LENGTH,                  &msg, wxT( "1.6" ) );
-    m_textCtrlViaLength->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_LENGTH_UNIT,             &tmp, DEFAULT_UNIT_SEL_MM );
-    m_choiceViaLength->SetSelection( tmp );
+    m_textCtrlViaLength->SetValue( cfg->m_ViaSize.length );
+    m_choiceViaLength->SetSelection( cfg->m_ViaSize.length_units );
 
-    aCfg->Read( KEYWORD_VS_PAD_DIA,                 &msg, wxT( "0.6" ) );
-    m_textCtrlViaPadDia->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_PAD_DIA_UNIT,            &tmp, DEFAULT_UNIT_SEL_MM );
-    m_choiceViaPadDia->SetSelection( tmp );
+    m_textCtrlViaPadDia->SetValue( cfg->m_ViaSize.pad_diameter );
+    m_choiceViaPadDia->SetSelection( cfg->m_ViaSize.pad_diameter_units );
 
-    aCfg->Read( KEYWORD_VS_CLEARANCE_DIA,           &msg, wxT( "1.0" ) );
-    m_textCtrlClearanceDia->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_CLEARANCE_DIA_UNIT,      &tmp, DEFAULT_UNIT_SEL_MM );
-    m_choiceClearanceDia->SetSelection( tmp );
+    m_textCtrlClearanceDia->SetValue( cfg->m_ViaSize.clearance_diameter );
+    m_choiceClearanceDia->SetSelection( cfg->m_ViaSize.clearance_diameter_units );
 
-    aCfg->Read( KEYWORD_VS_CH_IMPEDANCE,            &msg, wxT( "50" ) );
-    m_textCtrlImpedance->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_CH_IMPEDANCE_UNIT ,      &tmp, DEFAULT_UNIT_SEL_MM );
-    m_choiceImpedance->SetSelection( tmp );
+    m_textCtrlImpedance->SetValue( cfg->m_ViaSize.characteristic_impedance );
+    m_choiceImpedance->SetSelection( cfg->m_ViaSize.characteristic_impedance_units );
 
-    aCfg->Read( KEYWORD_VS_CURRENT,                 &msg, wxT( "1" ) );
-    m_textCtrlAppliedCurrent->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_RESISTIVITY,             &msg, wxT( "1.72e-8" ) );
-    m_textCtrlPlatingResistivity->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_PERMITTIVITY,            &msg, wxT( "4.5" ) );
-    m_textCtrlPlatingPermittivity->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_TEMP_DIFF,               &msg, wxT( "10" ) );
-    m_textCtrlTemperatureDiff->SetValue( msg );
-    aCfg->Read( KEYWORD_VS_PULSE_RISE_TIME,         &msg, wxT( "1" ) );
-    m_textCtrlRiseTime->SetValue( msg );
+    m_textCtrlAppliedCurrent->SetValue( cfg->m_ViaSize.applied_current );
+    m_textCtrlPlatingResistivity->SetValue( cfg->m_ViaSize.plating_resistivity );
+    m_textCtrlPlatingPermittivity->SetValue( cfg->m_ViaSize.permittivity );
+    m_textCtrlTemperatureDiff->SetValue( cfg->m_ViaSize.temp_rise );
+    m_textCtrlRiseTime->SetValue( cfg->m_ViaSize.pulse_rise_time );
 }
 
-void PCB_CALCULATOR_FRAME::VS_WriteConfig( wxConfigBase* aCfg )
+void PCB_CALCULATOR_FRAME::VS_WriteConfig()
 {
-    // Save current parameters values in config
-    aCfg->Write( KEYWORD_VS_HOLE_DIA,               m_textCtrlHoleDia->GetValue() );
-    aCfg->Write( KEYWORD_VS_HOLE_DIA_UNIT,          m_choiceHoleDia->GetSelection() );
-    aCfg->Write( KEYWORD_VS_THICKNESS,              m_textCtrlPlatingThickness->GetValue() );
-    aCfg->Write( KEYWORD_VS_THICKNESS_UNIT,         m_choicePlatingThickness->GetSelection() );
-    aCfg->Write( KEYWORD_VS_LENGTH,                 m_textCtrlViaLength->GetValue() );
-    aCfg->Write( KEYWORD_VS_LENGTH_UNIT,            m_choiceViaLength->GetSelection() );
-    aCfg->Write( KEYWORD_VS_PAD_DIA,                m_textCtrlViaPadDia->GetValue() );
-    aCfg->Write( KEYWORD_VS_PAD_DIA_UNIT,           m_choiceViaPadDia->GetSelection() );
-    aCfg->Write( KEYWORD_VS_CLEARANCE_DIA,          m_textCtrlClearanceDia->GetValue() );
-    aCfg->Write( KEYWORD_VS_CLEARANCE_DIA_UNIT,     m_choiceClearanceDia->GetSelection() );
-    aCfg->Write( KEYWORD_VS_CH_IMPEDANCE,           m_textCtrlImpedance->GetValue() );
-    aCfg->Write( KEYWORD_VS_CH_IMPEDANCE_UNIT,      m_choiceImpedance->GetSelection() );
-    aCfg->Write( KEYWORD_VS_CURRENT,                m_textCtrlAppliedCurrent->GetValue() );
-    aCfg->Write( KEYWORD_VS_RESISTIVITY,            m_textCtrlPlatingResistivity->GetValue() );
-    aCfg->Write( KEYWORD_VS_PERMITTIVITY,           m_textCtrlPlatingPermittivity->GetValue() );
-    aCfg->Write( KEYWORD_VS_TEMP_DIFF,              m_textCtrlTemperatureDiff->GetValue() );
-    aCfg->Write( KEYWORD_VS_PULSE_RISE_TIME,        m_textCtrlRiseTime->GetValue() );
+    auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
+
+    cfg->m_ViaSize.hole_diameter                  = m_textCtrlHoleDia->GetValue();
+    cfg->m_ViaSize.hole_diameter_units            = m_choiceHoleDia->GetSelection();
+    cfg->m_ViaSize.thickness                      = m_textCtrlPlatingThickness->GetValue();
+    cfg->m_ViaSize.thickness_units                = m_choicePlatingThickness->GetSelection();
+    cfg->m_ViaSize.length                         = m_textCtrlViaLength->GetValue();
+    cfg->m_ViaSize.length_units                   = m_choiceViaLength->GetSelection();
+    cfg->m_ViaSize.pad_diameter                   = m_textCtrlViaPadDia->GetValue();
+    cfg->m_ViaSize.pad_diameter_units             = m_choiceViaPadDia->GetSelection();
+    cfg->m_ViaSize.clearance_diameter             = m_textCtrlClearanceDia->GetValue();
+    cfg->m_ViaSize.clearance_diameter_units       = m_choiceClearanceDia->GetSelection();
+    cfg->m_ViaSize.characteristic_impedance       = m_textCtrlImpedance->GetValue();
+    cfg->m_ViaSize.characteristic_impedance_units = m_choiceImpedance->GetSelection();
+    cfg->m_ViaSize.applied_current                = m_textCtrlAppliedCurrent->GetValue();
+    cfg->m_ViaSize.plating_resistivity            = m_textCtrlPlatingResistivity->GetValue();
+    cfg->m_ViaSize.permittivity                   = m_textCtrlPlatingPermittivity->GetValue();
+    cfg->m_ViaSize.temp_rise                      = m_textCtrlTemperatureDiff->GetValue();
+    cfg->m_ViaSize.pulse_rise_time                = m_textCtrlRiseTime->GetValue();
 }
 
 void PCB_CALCULATOR_FRAME::OnViaCalculate( wxCommandEvent& event )
diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt
index 18f34022a3..8103bf075e 100644
--- a/pcbnew/CMakeLists.txt
+++ b/pcbnew/CMakeLists.txt
@@ -262,7 +262,7 @@ set( PCBNEW_CLASS_SRCS
     footprint_info_impl.cpp
     footprint_wizard.cpp
     footprint_editor_utils.cpp
-    footprint_editor_options.cpp
+    footprint_editor_settings.cpp
     fp_tree_synchronizing_adapter.cpp
     footprint_edit_frame.cpp
     footprint_libraries_utils.cpp
@@ -286,6 +286,7 @@ set( PCBNEW_CLASS_SRCS
     pcb_edit_frame.cpp
     pcbnew_config.cpp
     pcbnew_printout.cpp
+    pcbnew_settings.cpp
     pcb_legacy_draw_utils.cpp
     pcbplot.cpp
     plot_board_layers.cpp
@@ -592,6 +593,10 @@ target_link_libraries( pcbnew
     ${wxWidgets_LIBRARIES}
     )
 
+target_include_directories( pcbnew INTERFACE
+    $<TARGET_PROPERTY:nlohmann_json,INTERFACE_INCLUDE_DIRECTORIES>
+    )
+
 if( PCBNEW_LINK_MAPS )
     set_target_properties( pcbnew PROPERTIES
         LINK_FLAGS "-Wl,-cref,-Map=pcbnew.map" )
diff --git a/pcbnew/board_design_settings.cpp b/pcbnew/board_design_settings.cpp
index 18473ef9c5..7c059e6e2a 100644
--- a/pcbnew/board_design_settings.cpp
+++ b/pcbnew/board_design_settings.cpp
@@ -522,11 +522,11 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() :
     m_ProhibitOverlappingCourtyards = true;
 
     // Default ref text on fp creation. If empty, use footprint name as default
-    m_RefDefaultText = wxT( "REF**" );
+    m_RefDefaultText = "REF**";
     m_RefDefaultVisibility = true;
     m_RefDefaultlayer = int( F_SilkS );
     // Default value text on fp creation. If empty, use footprint name as default
-    m_ValueDefaultText = wxEmptyString;
+    m_ValueDefaultText = "";
     m_ValueDefaultVisibility = true;
     m_ValueDefaultlayer = int( F_Fab );
 }
diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp
index b75a2af53a..38754c151b 100644
--- a/pcbnew/class_board.cpp
+++ b/pcbnew/class_board.cpp
@@ -52,6 +52,7 @@
 #include <class_pcb_target.h>
 #include <connectivity/connectivity_data.h>
 #include <pgm_base.h>
+#include <pcbnew_settings.h>
 
 /**
  * A singleton item of this class is returned for a weak reference that no longer exists.
@@ -92,11 +93,11 @@ DELETED_BOARD_ITEM g_DeletedItem;
  */
 wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
 
-// Dummy general settings (defined colors are the default values) used to initialize the board.
-// These settings will be overriden later, depending on the draw frame that displays the board.
-// However, when a board is created by a python script, outside a frame, the colors must be set
-// so dummyColorsSettings provide this default initialization
-static PCB_GENERAL_SETTINGS dummyGeneralSettings( FRAME_PCB_EDITOR );
+// Dummy settings used to initialize the board.
+// This is needed because some APIs that make use of BOARD without the context of a frame or
+// application, and so the BOARD needs to store a valid pointer to a PCBNEW_SETTINGS even if
+// one hasn't been provided by the application.
+static PCBNEW_SETTINGS dummyGeneralSettings;
 
 BOARD::BOARD() :
     BOARD_ITEM_CONTAINER( (BOARD_ITEM*) NULL, PCB_T ),
diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h
index 9d2a565faf..e75b70972f 100644
--- a/pcbnew/class_board.h
+++ b/pcbnew/class_board.h
@@ -30,7 +30,6 @@
 #include <board_item_container.h>
 #include <class_module.h>
 #include <class_pad.h>
-#include <pcb_general_settings.h>
 #include <common.h> // PAGE_INFO
 #include <eda_rect.h>
 #include <layers_id_colors_and_visibility.h>
@@ -45,6 +44,7 @@ using std::unique_ptr;
 
 class PCB_BASE_FRAME;
 class PCB_EDIT_FRAME;
+class PCBNEW_SETTINGS;
 class PICKED_ITEMS_LIST;
 class BOARD;
 class ZONE_CONTAINER;
@@ -191,7 +191,7 @@ private:
     std::shared_ptr<CONNECTIVITY_DATA>      m_connectivity;
 
     BOARD_DESIGN_SETTINGS   m_designSettings;
-    PCB_GENERAL_SETTINGS*   m_generalSettings;      ///< reference only; I have no ownership
+    PCBNEW_SETTINGS*        m_generalSettings;      ///< reference only; I have no ownership
     PAGE_INFO               m_paper;
     TITLE_BLOCK             m_titles;               ///< text in lower right of screen and plots
     PCB_PLOT_PARAMS         m_plotOptions;
@@ -553,17 +553,11 @@ public:
 
     wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
 
-    /**
-     * Function GetColorSettings
-     * @return the current COLORS_DESIGN_SETTINGS in use
-     */
-    const COLORS_DESIGN_SETTINGS& Colors() const { return m_generalSettings->Colors(); }
+    const PCBNEW_SETTINGS& GeneralSettings() const { return *m_generalSettings; }
 
-    const PCB_GENERAL_SETTINGS& GeneralSettings() const { return *m_generalSettings; }
-
-    void SetGeneralSettings( PCB_GENERAL_SETTINGS* aGeneralSettings )
+    void SetGeneralSettings( PCBNEW_SETTINGS* aSettings )
     {
-        m_generalSettings = aGeneralSettings;
+        m_generalSettings = aSettings;
     }
 
     /**
diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp
index 8d72e511a5..3e5f82ca5d 100644
--- a/pcbnew/class_dimension.cpp
+++ b/pcbnew/class_dimension.cpp
@@ -33,11 +33,14 @@
 #include <bitmaps.h>
 #include <pcb_edit_frame.h>
 
-#include <class_board.h>
-#include <class_pcb_text.h>
-#include <class_dimension.h>
 #include <base_units.h>
-#include <math/util.h>      // for KiROUND
+#include <class_board.h>
+#include <class_dimension.h>
+#include <class_pcb_text.h>
+#include <math/util.h> // for KiROUND
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
 
 
 DIMENSION::DIMENSION( BOARD_ITEM* aParent )
@@ -362,7 +365,7 @@ void DIMENSION::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset )
 
     m_Text.Print( aFrame, DC, offset );
 
-    auto gcolor = aFrame->Settings().Colors().GetLayerColor( m_Layer );
+    COLOR4D gcolor = Pgm().GetSettingsManager().GetColorSettings()->GetColor( m_Layer );
     auto displ_opts = aFrame->GetDisplayOptions();
     bool filled = displ_opts.m_DisplayDrawItemsFill;
     int  width   = m_Width;
diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp
index a93204d760..5ab31f8d1d 100644
--- a/pcbnew/class_drawsegment.cpp
+++ b/pcbnew/class_drawsegment.cpp
@@ -39,6 +39,9 @@
 #include <class_drawsegment.h>
 #include <base_units.h>
 #include <math/util.h>      // for KiROUND
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
 
 
 DRAWSEGMENT::DRAWSEGMENT( BOARD_ITEM* aParent, KICAD_T idtype ) :
@@ -350,7 +353,7 @@ void DRAWSEGMENT::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& aOffse
     if( brd->IsLayerVisible( GetLayer() ) == false )
         return;
 
-    auto color = aFrame->Settings().Colors().GetLayerColor( GetLayer() );
+    COLOR4D color = Pgm().GetSettingsManager().GetColorSettings()->GetColor( GetLayer() );
     auto displ_opts = aFrame->GetDisplayOptions();
 
     l_trace = m_Width >> 1;         // half trace width
diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp
index 9aac2f3a04..ac7d609e82 100644
--- a/pcbnew/class_edge_mod.cpp
+++ b/pcbnew/class_edge_mod.cpp
@@ -43,6 +43,9 @@
 #include <base_units.h>
 #include <bitmaps.h>
 #include <math/util.h>      // for KiROUND
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
 
 #include <pcb_edit_frame.h>
 #include <class_board.h>
@@ -127,7 +130,7 @@ void EDGE_MODULE::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset
     if( !module || !brd->IsLayerVisible( m_Layer ) )
         return;
 
-    auto color = aFrame->Settings().Colors().GetLayerColor( m_Layer );
+    COLOR4D color = Pgm().GetSettingsManager().GetColorSettings()->GetColor( m_Layer );
     auto displ_opts = aFrame->GetDisplayOptions();
 
     ux0 = m_Start.x - offset.x;
diff --git a/pcbnew/class_pcb_target.cpp b/pcbnew/class_pcb_target.cpp
index 464e73ef35..297d2c367e 100644
--- a/pcbnew/class_pcb_target.cpp
+++ b/pcbnew/class_pcb_target.cpp
@@ -41,6 +41,9 @@
 #include <class_board.h>
 #include <class_pcb_target.h>
 #include <base_units.h>
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
 
 
 PCB_TARGET::PCB_TARGET( BOARD_ITEM* aParent ) :
@@ -86,7 +89,7 @@ void PCB_TARGET::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset
     if( brd->IsLayerVisible( m_Layer ) == false )
         return;
 
-    auto gcolor = aFrame->Settings().Colors().GetLayerColor( m_Layer );
+    COLOR4D gcolor = Pgm().GetSettingsManager().GetColorSettings()->GetColor( m_Layer );
     auto displ_opts = aFrame->GetDisplayOptions();
     bool filled = displ_opts.m_DisplayDrawItemsFill;
     width = m_Width;
diff --git a/pcbnew/class_pcb_text.cpp b/pcbnew/class_pcb_text.cpp
index 55f0a5e098..92961210d9 100644
--- a/pcbnew/class_pcb_text.cpp
+++ b/pcbnew/class_pcb_text.cpp
@@ -40,6 +40,9 @@
 #include <msgpanel.h>
 #include <base_units.h>
 #include <bitmaps.h>
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
 
 #include <class_board.h>
 #include <class_pcb_text.h>
@@ -71,9 +74,9 @@ void TEXTE_PCB::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& offset )
     if( brd->IsLayerVisible( m_Layer ) == false )
         return;
 
-    auto                 color = aFrame->Settings().Colors().GetLayerColor( m_Layer );
-    EDA_DRAW_MODE_T      fillmode = FILLED;
-    auto&                displ_opts = aFrame->GetDisplayOptions();
+    auto            color      = Pgm().GetSettingsManager().GetColorSettings()->GetColor( m_Layer );
+    EDA_DRAW_MODE_T fillmode   = FILLED;
+    auto&           displ_opts = aFrame->GetDisplayOptions();
 
     if( displ_opts.m_DisplayDrawItemsFill == SKETCH )
         fillmode = SKETCH;
diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp
index 44e0a533a0..2e9d70f2f7 100644
--- a/pcbnew/class_text_mod.cpp
+++ b/pcbnew/class_text_mod.cpp
@@ -38,6 +38,9 @@
 #include <class_module.h>
 #include <view/view.h>
 #include <pcbnew.h>
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
 
 
 TEXTE_MODULE::TEXTE_MODULE( MODULE* parent, TEXT_TYPE text_type ) :
@@ -263,7 +266,7 @@ void TEXTE_MODULE::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOff
     wxASSERT( m_Parent );
 
     BOARD*         brd = GetBoard( );
-    KIGFX::COLOR4D color = aFrame->Settings().Colors().GetLayerColor( GetLayer() );
+    KIGFX::COLOR4D color = Pgm().GetSettingsManager().GetColorSettings()->GetColor( GetLayer() );
     PCB_LAYER_ID   text_layer = GetLayer();
 
     if( !brd->IsLayerVisible( m_Layer )
@@ -284,7 +287,7 @@ void TEXTE_MODULE::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOff
         if( !brd->IsElementVisible( LAYER_MOD_TEXT_INVISIBLE ) )
             return;
 
-        color = aFrame->Settings().Colors().GetItemColor( LAYER_MOD_TEXT_INVISIBLE );
+        color = Pgm().GetSettingsManager().GetColorSettings()->GetColor( LAYER_MOD_TEXT_INVISIBLE );
     }
 
     // Draw mode compensation for the width
diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp
index c6063bdc66..da18893f1d 100644
--- a/pcbnew/class_track.cpp
+++ b/pcbnew/class_track.cpp
@@ -40,6 +40,9 @@
 #include <bitmaps.h>
 #include <view/view.h>
 #include <math/util.h>      // for KiROUND
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
 
 /**
  * Function ShowClearance
@@ -393,7 +396,7 @@ void VIA::SanitizeLayers()
 void TRACK::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOffset )
 {
     BOARD* brd = GetBoard();
-    auto   color = aFrame->Settings().Colors().GetLayerColor( m_Layer );
+    auto   color = Pgm().GetSettingsManager().GetColorSettings()->GetColor( m_Layer );
 
     if( !brd->IsLayerVisible( m_Layer ) || !brd->IsElementVisible( LAYER_TRACKS ) )
         return;
@@ -463,7 +466,7 @@ void VIA::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOffset )
     PCB_SCREEN* screen     = aFrame->GetScreen();
     auto&       displ_opts = aFrame->GetDisplayOptions();
     BOARD*      brd        = GetBoard();
-    COLOR4D     color      = aFrame->Settings().Colors().GetItemColor(
+    COLOR4D     color      = Pgm().GetSettingsManager().GetColorSettings()->GetColor(
             LAYER_VIAS + static_cast<int>( GetViaType() ) );
 
     if( displ_opts.m_DisplayViaFill == FILLED )
diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp
index ef40f4b29a..cd3fd0ee21 100644
--- a/pcbnew/class_zone.cpp
+++ b/pcbnew/class_zone.cpp
@@ -41,6 +41,9 @@
 #include <math_for_graphics.h>
 #include <geometry/polygon_test_point_inside.h>
 #include <math/util.h>      // for KiROUND
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
 
 
 ZONE_CONTAINER::ZONE_CONTAINER( BOARD_ITEM_CONTAINER* aParent, bool aInModule )
@@ -376,7 +379,7 @@ void ZONE_CONTAINER::Print( PCB_BASE_FRAME* aFrame, wxDC* DC, const wxPoint& off
 
     assert( draw_layer != UNDEFINED_LAYER );
 
-    auto color = aFrame->Settings().Colors().GetLayerColor( draw_layer );
+    COLOR4D color = Pgm().GetSettingsManager().GetColorSettings()->GetColor( draw_layer );
 
     auto displ_opts = aFrame->GetDisplayOptions();
 
@@ -424,10 +427,10 @@ void ZONE_CONTAINER::PrintFilledArea( PCB_BASE_FRAME* aFrame, wxDC* DC, const wx
 {
     static std::vector <wxPoint> CornersBuffer;
 
-    BOARD*               brd = GetBoard();
-    KIGFX::COLOR4D       color = aFrame->Settings().Colors().GetLayerColor( GetLayer() );
-    auto&                displ_opts = aFrame->GetDisplayOptions();
-    bool                 outline_mode = displ_opts.m_DisplayZonesMode == 2;
+    BOARD*  brd          = GetBoard();
+    COLOR4D color        = Pgm().GetSettingsManager().GetColorSettings()->GetColor( GetLayer() );
+    auto&   displ_opts   = aFrame->GetDisplayOptions();
+    bool    outline_mode = displ_opts.m_DisplayZonesMode == 2;
 
     if( DC == NULL )
         return;
diff --git a/pcbnew/dialogs/dialog_choose_footprint.cpp b/pcbnew/dialogs/dialog_choose_footprint.cpp
index fb8b96b6ac..14161990ac 100644
--- a/pcbnew/dialogs/dialog_choose_footprint.cpp
+++ b/pcbnew/dialogs/dialog_choose_footprint.cpp
@@ -31,17 +31,15 @@
 #include <wx/splitter.h>
 #include <wx/timer.h>
 #include <pcb_base_frame.h>
+#include <pcbnew_settings.h>
+#include <pgm_base.h>
 #include <fp_lib_table.h>
+#include <settings/settings_manager.h>
 #include <widgets/lib_tree.h>
 #include <widgets/footprint_preview_widget.h>
 #include <widgets/footprint_select_widget.h>
 #include <kiface_i.h>
 
-#define FP_CHOOSER_HSASH       wxT( "FootprintChooserHSashPosition" )
-#define FP_CHOOSER_VSASH       wxT( "FootprintChooserVSashPosition" )
-#define FP_CHOOSER_WIDTH_KEY   wxT( "FootprintChooserWidth" )
-#define FP_CHOOSER_HEIGHT_KEY  wxT( "FootprintChooserHeight" )
-
 
 DIALOG_CHOOSE_FOOTPRINT::DIALOG_CHOOSE_FOOTPRINT( PCB_BASE_FRAME* aParent,
                                                   const wxString& aTitle,
@@ -54,8 +52,6 @@ DIALOG_CHOOSE_FOOTPRINT::DIALOG_CHOOSE_FOOTPRINT( PCB_BASE_FRAME* aParent,
           m_parent( aParent ),
           m_external_browser_requested( false )
 {
-    m_config = Kiface().KifaceSettings();
-
     auto          sizer = new wxBoxSizer( wxVERTICAL );
     wxHtmlWindow* details = nullptr;
 
@@ -117,16 +113,26 @@ DIALOG_CHOOSE_FOOTPRINT::DIALOG_CHOOSE_FOOTPRINT( PCB_BASE_FRAME* aParent,
 
     Layout();
 
+    auto cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
+
     // We specify the width of the right window (m_symbol_view_panel), because specify
     // the width of the left window does not work as expected when SetSashGravity() is called
-    m_hsplitter->SetSashPosition( m_config->Read( FP_CHOOSER_HSASH, HorizPixelsFromDU( 220 ) ) );
+    if( cfg->m_FootprintChooser.sash_h < 0 )
+        cfg->m_FootprintChooser.sash_h = HorizPixelsFromDU( 220 );
+
+    m_hsplitter->SetSashPosition( cfg->m_FootprintChooser.sash_h );
+
+    if( cfg->m_FootprintChooser.sash_v < 0 )
+        cfg->m_FootprintChooser.sash_v = HorizPixelsFromDU( 230 );
 
     if( m_vsplitter )
-        m_vsplitter->SetSashPosition( m_config->Read( FP_CHOOSER_VSASH, VertPixelsFromDU( 230 ) ) );
+        m_vsplitter->SetSashPosition( cfg->m_FootprintChooser.sash_v );
 
-    wxSize dlgSize( m_config->Read( FP_CHOOSER_WIDTH_KEY, HorizPixelsFromDU( 440 ) ),
-                    m_config->Read( FP_CHOOSER_HEIGHT_KEY, VertPixelsFromDU( 340 ) ) );
-    SetSize( dlgSize );
+    int w = cfg->m_FootprintChooser.width < 0 ?
+            HorizPixelsFromDU( 440 ) : cfg->m_FootprintChooser.width;
+    int h = cfg->m_FootprintChooser.height < 0 ?
+            HorizPixelsFromDU( 340 ) : cfg->m_FootprintChooser.height;
+    SetSize( wxSize( w, h ) );
 
     SetInitialFocus( m_tree );
     okButton->SetDefault();
@@ -145,13 +151,14 @@ DIALOG_CHOOSE_FOOTPRINT::~DIALOG_CHOOSE_FOOTPRINT()
     m_dbl_click_timer->Stop();
     delete m_dbl_click_timer;
 
-    m_config->Write( FP_CHOOSER_WIDTH_KEY, GetSize().x );
-    m_config->Write( FP_CHOOSER_HEIGHT_KEY, GetSize().y );
+    auto cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
 
-    m_config->Write( FP_CHOOSER_HSASH, m_hsplitter->GetSashPosition() );
+    cfg->m_FootprintChooser.width = GetSize().x;
+    cfg->m_FootprintChooser.height = GetSize().y;
+    cfg->m_FootprintChooser.sash_h = m_hsplitter->GetSashPosition();
 
     if( m_vsplitter )
-        m_config->Write( FP_CHOOSER_VSASH, m_vsplitter->GetSashPosition() );
+        cfg->m_FootprintChooser.sash_v = m_vsplitter->GetSashPosition();
 }
 
 
diff --git a/pcbnew/dialogs/dialog_choose_footprint.h b/pcbnew/dialogs/dialog_choose_footprint.h
index 3efc6399ed..a926d1853c 100644
--- a/pcbnew/dialogs/dialog_choose_footprint.h
+++ b/pcbnew/dialogs/dialog_choose_footprint.h
@@ -133,8 +133,6 @@ protected:
      */
     void OnComponentSelected( wxCommandEvent& aEvent );
 
-    wxConfigBase*             m_config;
-
     wxTimer*                  m_dbl_click_timer;
     wxButton*                 m_browser_button;
     wxSplitterWindow*         m_hsplitter;
diff --git a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp
index 9b5f88ecaa..1a673a8e07 100644
--- a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp
+++ b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.cpp
@@ -32,42 +32,25 @@
 #include <dialog_cleanup_tracks_and_vias.h>
 #include <kiface_i.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <reporter.h>
 #include <tool/tool_manager.h>
 #include <tools/pcb_actions.h>
 #include <tracks_cleaner.h>
 #include <wx_html_report_panel.h>
 
-// Keywords for read and write config
-#define CleanupViaKey wxT( "DialogCleanupVias" )
-#define MergeKey wxT( "DialogCleanupMergeSegments" )
-#define UnconnectedKey wxT( "DialogCleanupUnconnected" )
-#define ShortCircuitKey wxT( "DialogCleanupShortCircuit" )
-#define TracksInPadKey wxT( "DialogCleanupTracksInPads" )
-
 
 DIALOG_CLEANUP_TRACKS_AND_VIAS::DIALOG_CLEANUP_TRACKS_AND_VIAS( PCB_EDIT_FRAME* aParentFrame ):
         DIALOG_CLEANUP_TRACKS_AND_VIAS_BASE( aParentFrame ),
     m_parentFrame( aParentFrame )
 {
-    m_config = Kiface().KifaceSettings();
-    m_config->SetPath( "/dialogs/cleanup_tracks/" );
+    auto cfg = m_parentFrame->GetSettings();
 
-    bool value;
-    m_config->Read( CleanupViaKey, &value, true );
-    m_cleanViasOpt->SetValue( value );
-
-    m_config->Read( MergeKey, &value, true );
-    m_mergeSegmOpt->SetValue( value );
-
-    m_config->Read( UnconnectedKey, &value, true );
-    m_deleteUnconnectedOpt->SetValue( value );
-
-    m_config->Read( ShortCircuitKey, &value, true );
-    m_cleanShortCircuitOpt->SetValue( value );
-
-    m_config->Read( TracksInPadKey, &value, true );
-    m_deleteTracksInPadsOpt->SetValue( value );
+    m_cleanViasOpt->SetValue( cfg->m_Cleanup.cleanup_vias );
+    m_mergeSegmOpt->SetValue( cfg->m_Cleanup.merge_segments );
+    m_deleteUnconnectedOpt->SetValue( cfg->m_Cleanup.cleanup_unconnected );
+    m_cleanShortCircuitOpt->SetValue( cfg->m_Cleanup.cleanup_short_circuits );
+    m_deleteTracksInPadsOpt->SetValue( cfg->m_Cleanup.cleanup_tracks_in_pad );
 
     // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
     // that requires us to correct the button labels here.
@@ -81,11 +64,13 @@ DIALOG_CLEANUP_TRACKS_AND_VIAS::DIALOG_CLEANUP_TRACKS_AND_VIAS( PCB_EDIT_FRAME*
 
 DIALOG_CLEANUP_TRACKS_AND_VIAS::~DIALOG_CLEANUP_TRACKS_AND_VIAS()
 {
-    m_config->Write( CleanupViaKey, m_cleanViasOpt->GetValue() );
-    m_config->Write( MergeKey, m_mergeSegmOpt->GetValue() );
-    m_config->Write( UnconnectedKey, m_deleteUnconnectedOpt->GetValue() );
-    m_config->Write( ShortCircuitKey, m_cleanShortCircuitOpt->GetValue() );
-    m_config->Write( TracksInPadKey, m_deleteTracksInPadsOpt->GetValue() );
+    auto cfg = m_parentFrame->GetSettings();
+
+    cfg->m_Cleanup.cleanup_vias           = m_cleanViasOpt->GetValue();
+    cfg->m_Cleanup.merge_segments         = m_mergeSegmOpt->GetValue();
+    cfg->m_Cleanup.cleanup_unconnected    = m_deleteUnconnectedOpt->GetValue();
+    cfg->m_Cleanup.cleanup_short_circuits = m_cleanShortCircuitOpt->GetValue();
+    cfg->m_Cleanup.cleanup_tracks_in_pad  = m_deleteTracksInPadsOpt->GetValue();
 
     for( DRC_ITEM* item : m_items )
         delete item;
diff --git a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.h b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.h
index 9b72616faa..91f02a8273 100644
--- a/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.h
+++ b/pcbnew/dialogs/dialog_cleanup_tracks_and_vias.h
@@ -28,7 +28,6 @@
 #include <dialog_cleanup_tracks_and_vias_base.h>
 
 #include <drc/drc.h>
-#include <wx/config.h>
 
 
 class PCB_EDIT_FRAME;
@@ -38,7 +37,6 @@ class DIALOG_CLEANUP_TRACKS_AND_VIAS: public DIALOG_CLEANUP_TRACKS_AND_VIAS_BASE
 {
     PCB_EDIT_FRAME* m_parentFrame;
     DRC_LIST        m_items;
-    wxConfigBase*   m_config;
 
     void doCleanup( bool aDryRun );
 
diff --git a/pcbnew/dialogs/dialog_copper_zones.cpp b/pcbnew/dialogs/dialog_copper_zones.cpp
index afb7818a0c..c505a5af2b 100644
--- a/pcbnew/dialogs/dialog_copper_zones.cpp
+++ b/pcbnew/dialogs/dialog_copper_zones.cpp
@@ -27,6 +27,7 @@
 #include <kiface_i.h>
 #include <confirm.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <zones.h>
 #include <bitmaps.h>
 #include <widgets/unit_binder.h>
@@ -43,7 +44,6 @@ public:
 
 private:
     PCB_BASE_FRAME* m_Parent;
-    wxConfigBase*   m_Config;               // Current config
 
     bool            m_settingsExported;     // settings will be written to all other zones
 
@@ -117,7 +117,6 @@ DIALOG_COPPER_ZONE::DIALOG_COPPER_ZONE( PCB_BASE_FRAME* aParent, ZONE_SETTINGS*
     m_gridStyleGap( aParent, m_staticTextGridGap, m_tcGridStyleGap, m_GridStyleGapUnits, false )
 {
     m_Parent = aParent;
-    m_Config = Kiface().KifaceSettings();
     m_bitmapNoNetWarning->SetBitmap( KiBitmap( dialog_warning_xpm ) );
 
     m_ptr = aSettings;
@@ -184,13 +183,13 @@ bool DIALOG_COPPER_ZONE::TransferDataToWindow()
     m_NetFiltering = false;
     m_NetSortingByPadCount = true;
 
-    if( m_Config )
-    {
-        int opt = m_Config->Read( ZONE_NET_SORT_OPTION_KEY, 1l );
-        m_NetFiltering = opt >= 2;
-        m_NetSortingByPadCount = opt % 2;
-        m_Config->Read( ZONE_NET_FILTER_STRING_KEY, netNameDoNotShowFilter );
-    }
+    auto cfg = m_Parent->GetSettings();
+
+    int opt = cfg->m_Zones.net_sort_mode;
+    m_NetFiltering = opt >= 2;
+    m_NetSortingByPadCount = opt % 2;
+
+    netNameDoNotShowFilter = cfg->m_Zones.net_filter;
 
     m_ShowNetNameFilter->SetValue( m_netNameShowFilter );
     m_DoNotShowNetNameFilter->SetValue( netNameDoNotShowFilter );
@@ -358,12 +357,10 @@ bool DIALOG_COPPER_ZONE::AcceptOptions( bool aUseExportableSetupOnly )
         break;
     }
 
-    if( m_Config )
-    {
-        m_Config->Write( ZONE_NET_OUTLINES_STYLE_KEY, (long) m_settings.m_Zone_HatchingStyle );
-        wxString filter = m_DoNotShowNetNameFilter->GetValue();
-        m_Config->Write( ZONE_NET_FILTER_STRING_KEY, filter );
-    }
+    auto cfg = m_Parent->GetSettings();
+
+    cfg->m_Zones.hatching_style = static_cast<int>( m_settings.m_Zone_HatchingStyle );
+    cfg->m_Zones.net_filter = m_DoNotShowNetNameFilter->GetValue().ToStdString();
 
     m_netNameShowFilter = m_ShowNetNameFilter->GetValue();
 
@@ -388,17 +385,10 @@ bool DIALOG_COPPER_ZONE::AcceptOptions( bool aUseExportableSetupOnly )
         return false;
     }
 
-    if( m_Config )
-    {
-        ConfigBaseWriteDouble( m_Config, ZONE_CLEARANCE_WIDTH_STRING_KEY,
-                               (double) m_settings.m_ZoneClearance / IU_PER_MILS );
-        ConfigBaseWriteDouble( m_Config, ZONE_MIN_THICKNESS_WIDTH_STRING_KEY,
-                               (double) m_settings.m_ZoneMinThickness / IU_PER_MILS );
-        ConfigBaseWriteDouble( m_Config, ZONE_THERMAL_RELIEF_GAP_STRING_KEY,
-                               (double) m_settings.m_ThermalReliefGap / IU_PER_MILS );
-        ConfigBaseWriteDouble( m_Config, ZONE_THERMAL_RELIEF_COPPER_WIDTH_STRING_KEY,
-                               (double) m_settings.m_ThermalReliefCopperBridge / IU_PER_MILS );
-    }
+    cfg->m_Zones.clearance                   = Iu2Mils( m_settings.m_ZoneClearance );
+    cfg->m_Zones.min_thickness               = Iu2Mils( m_settings.m_ZoneMinThickness );
+    cfg->m_Zones.thermal_relief_gap          = Iu2Mils( m_settings.m_ThermalReliefGap );
+    cfg->m_Zones.thermal_relief_copper_width = Iu2Mils( m_settings.m_ThermalReliefCopperBridge );
 
     // If we use only exportable to others zones parameters, exit here:
     if( aUseExportableSetupOnly )
@@ -478,17 +468,15 @@ void DIALOG_COPPER_ZONE::OnNetSortingOptionSelected( wxCommandEvent& event )
 
     buildAvailableListOfNets();
 
-    if( m_Config )
-    {
-        long configValue = m_NetFiltering ? 2 : 0;
+    auto cfg = m_Parent->GetSettings();
 
-        if( m_NetSortingByPadCount )
-            configValue += 1;
+    int configValue = m_NetFiltering ? 2 : 0;
 
-        m_Config->Write( ZONE_NET_SORT_OPTION_KEY, configValue );
-        wxString Filter = m_DoNotShowNetNameFilter->GetValue();
-        m_Config->Write( ZONE_NET_FILTER_STRING_KEY, Filter );
-    }
+    if( m_NetSortingByPadCount )
+        configValue += 1;
+
+    cfg->m_Zones.net_sort_mode = configValue;
+    cfg->m_Zones.net_filter = m_DoNotShowNetNameFilter->GetValue().ToStdString();
 }
 
 
diff --git a/pcbnew/dialogs/dialog_drc.cpp b/pcbnew/dialogs/dialog_drc.cpp
index c452706a3a..a1286d1571 100644
--- a/pcbnew/dialogs/dialog_drc.cpp
+++ b/pcbnew/dialogs/dialog_drc.cpp
@@ -31,6 +31,7 @@
 #include <fctsys.h>
 #include <kiface_i.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <pgm_base.h>
 #include <tool/tool_manager.h>
 #include <tools/pcb_actions.h>
@@ -41,11 +42,6 @@
  * and run DRC tests
  */
 
-// Keywords for read and write config
-#define DrcRefillZonesKey       wxT( "RefillZonesBeforeDrc" )
-#define DrcTrackToZoneTestKey   wxT( "DrcTrackToZoneTest" )
-#define DrcTestFootprintsKey    wxT( "DrcTestFootprints" )
-
 
 DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL(
         DRC* aTester, PCB_EDIT_FRAME* aEditorFrame, wxWindow* aParent )
@@ -58,7 +54,6 @@ DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL(
 {
     SetName( DIALOG_DRC_WINDOW_NAME ); // Set a window name to be able to find it
 
-    m_config       = Kiface().KifaceSettings();
     m_tester       = aTester;
     m_brdEditor    = aEditorFrame;
     m_currentBoard = m_brdEditor->GetBoard();
@@ -81,9 +76,11 @@ DIALOG_DRC_CONTROL::DIALOG_DRC_CONTROL(
 
 DIALOG_DRC_CONTROL::~DIALOG_DRC_CONTROL()
 {
-    m_config->Write( DrcRefillZonesKey, m_cbRefillZones->GetValue() );
-    m_config->Write( DrcTrackToZoneTestKey, m_cbReportTracksToZonesErrors->GetValue() );
-    m_config->Write( DrcTestFootprintsKey, m_cbTestFootprints->GetValue() );
+    auto cfg = m_brdEditor->GetSettings();
+
+    cfg->m_DrcDialog.refill_zones       = m_cbRefillZones->GetValue();
+    cfg->m_DrcDialog.test_track_to_zone = m_cbReportAllTrackErrors->GetValue();
+    cfg->m_DrcDialog.test_footprints    = m_cbTestFootprints->GetValue();
 }
 
 
@@ -126,14 +123,11 @@ void DIALOG_DRC_CONTROL::InitValues()
 
     DisplayDRCValues();
 
-    // read options
-    bool value;
-    m_config->Read( DrcRefillZonesKey, &value, false );
-    m_cbRefillZones->SetValue( value );
-    m_config->Read( DrcTrackToZoneTestKey, &value, false );
-    m_cbReportTracksToZonesErrors->SetValue( value );
-    m_config->Read( DrcTestFootprintsKey, &value, false );
-    m_cbTestFootprints->SetValue( value );
+    auto cfg = m_brdEditor->GetSettings();
+
+    m_cbRefillZones->SetValue( cfg->m_DrcDialog.refill_zones );
+    m_cbReportAllTrackErrors->SetValue( cfg->m_DrcDialog.test_track_to_zone );
+    m_cbTestFootprints->SetValue( cfg->m_DrcDialog.test_footprints );
 
     Layout(); // adding the units above expanded Clearance text, now resize.
 
diff --git a/pcbnew/dialogs/dialog_drc.h b/pcbnew/dialogs/dialog_drc.h
index 4dac4741b0..2f228905c2 100644
--- a/pcbnew/dialogs/dialog_drc.h
+++ b/pcbnew/dialogs/dialog_drc.h
@@ -162,7 +162,6 @@ private:
     BOARD*              m_currentBoard;     // the board currently on test
     DRC*                m_tester;
     PCB_EDIT_FRAME*     m_brdEditor;
-    wxConfigBase*       m_config;
 
     wxString            m_markersTitleTemplate;
     wxString            m_unconnectedTitleTemplate;
diff --git a/pcbnew/dialogs/dialog_edit_footprint_for_BoardEditor.cpp b/pcbnew/dialogs/dialog_edit_footprint_for_BoardEditor.cpp
index 11bc1648fd..d17b0c8560 100644
--- a/pcbnew/dialogs/dialog_edit_footprint_for_BoardEditor.cpp
+++ b/pcbnew/dialogs/dialog_edit_footprint_for_BoardEditor.cpp
@@ -24,25 +24,27 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <kiface_i.h>
-#include <confirm.h>
-#include <pcbnew.h>
-#include <pgm_base.h>
-#include <pcb_edit_frame.h>
+#include <3d_viewer/eda_3d_viewer.h>
+#include <bitmaps.h>
 #include <board_commit.h>
 #include <board_design_settings.h>
-#include <dialog_text_entry.h>
 #include <class_module.h>
-#include <validators.h>
-#include <widgets/wx_grid.h>
-#include <widgets/text_ctrl_eval.h>
+#include <confirm.h>
+#include <dialog_text_entry.h>
+#include <fctsys.h>
 #include <filename_resolver.h>
-#include "3d_cache/dialogs/panel_prev_model.h"
+#include <kiface_i.h>
+#include <math/util.h> // for KiROUND
+#include <pcb_edit_frame.h>
+#include <pcbnew.h>
+#include <pcbnew_settings.h>
+#include <pgm_base.h>
+#include <validators.h>
+#include <widgets/text_ctrl_eval.h>
+#include <widgets/wx_grid.h>
+
 #include "3d_cache/dialogs/3d_cache_dialogs.h"
-#include <bitmaps.h>
-#include <3d_viewer/eda_3d_viewer.h>
-#include <math/util.h>      // for KiROUND
+#include "3d_cache/dialogs/panel_prev_model.h"
 
 #include <dialog_edit_footprint_for_BoardEditor.h>
 
@@ -64,8 +66,6 @@ DIALOG_FOOTPRINT_BOARD_EDITOR::DIALOG_FOOTPRINT_BOARD_EDITOR( PCB_EDIT_FRAME* aP
     m_initialFocus( true ),
     m_inSelect( false )
 {
-    m_config = Kiface().KifaceSettings();
-
     m_frame     = aParent;
     m_footprint = aModule;
 
@@ -90,9 +90,7 @@ DIALOG_FOOTPRINT_BOARD_EDITOR::DIALOG_FOOTPRINT_BOARD_EDITOR( PCB_EDIT_FRAME* aP
     m_modelsGrid->PushEventHandler( new GRID_TRICKS( m_modelsGrid ) );
 
     // Show/hide text item columns according to the user's preference
-    wxString shownColumns;
-    m_config->Read( FootprintTextShownColumnsKey, &shownColumns, wxT( "0 1 2 3 4 5 6" ) );
-    m_itemsGrid->ShowHideColumns( shownColumns );
+    m_itemsGrid->ShowHideColumns( m_frame->GetSettings()->m_FootprintTextShownColumns );
 
     // Set up the 3D models grid
     wxGridCellAttr* attr = new wxGridCellAttr;
@@ -158,7 +156,8 @@ DIALOG_FOOTPRINT_BOARD_EDITOR::DIALOG_FOOTPRINT_BOARD_EDITOR( PCB_EDIT_FRAME* aP
 
 DIALOG_FOOTPRINT_BOARD_EDITOR::~DIALOG_FOOTPRINT_BOARD_EDITOR()
 {
-    m_config->Write( FootprintTextShownColumnsKey, m_itemsGrid->GetShownColumns() );
+    m_frame->GetSettings()->m_FootprintTextShownColumns =
+            m_itemsGrid->GetShownColumns().ToStdString();
 
     // Prevents crash bug in wxGrid's d'tor
     m_itemsGrid->DestroyTable( m_texts );
diff --git a/pcbnew/dialogs/dialog_edit_footprint_for_BoardEditor.h b/pcbnew/dialogs/dialog_edit_footprint_for_BoardEditor.h
index 07fe3c4784..845ce9ba19 100644
--- a/pcbnew/dialogs/dialog_edit_footprint_for_BoardEditor.h
+++ b/pcbnew/dialogs/dialog_edit_footprint_for_BoardEditor.h
@@ -41,7 +41,6 @@ class PANEL_PREV_3D;
 class DIALOG_FOOTPRINT_BOARD_EDITOR: public DIALOG_FOOTPRINT_BOARD_EDITOR_BASE
 {
 private:
-    wxConfigBase*                    m_config;
     PCB_EDIT_FRAME*                  m_frame;
     MODULE*                          m_footprint;
 
diff --git a/pcbnew/dialogs/dialog_edit_footprint_for_fp_editor.cpp b/pcbnew/dialogs/dialog_edit_footprint_for_fp_editor.cpp
index 5dd530f24e..e712167c61 100644
--- a/pcbnew/dialogs/dialog_edit_footprint_for_fp_editor.cpp
+++ b/pcbnew/dialogs/dialog_edit_footprint_for_fp_editor.cpp
@@ -39,6 +39,7 @@
 #include <widgets/text_ctrl_eval.h>
 #include <class_module.h>
 #include <footprint_edit_frame.h>
+#include <footprint_editor_settings.h>
 #include <dialog_edit_footprint_for_fp_editor.h>
 #include "filename_resolver.h"
 #include <pgm_base.h>
@@ -47,7 +48,6 @@
 
 #include <fp_lib_table.h>
 
-#define LibFootprintTextShownColumnsKey   wxT( "LibFootprintTextShownColumns" )
 
 int DIALOG_FOOTPRINT_FP_EDITOR::m_page = 0;     // remember the last open page during session
 
@@ -60,8 +60,6 @@ DIALOG_FOOTPRINT_FP_EDITOR::DIALOG_FOOTPRINT_FP_EDITOR( FOOTPRINT_EDIT_FRAME* aP
     m_solderPaste( aParent, m_SolderPasteMarginLabel, m_SolderPasteMarginCtrl, m_SolderPasteMarginUnits ),
     m_inSelect( false )
 {
-    m_config = Kiface().KifaceSettings();
-
     m_frame = aParent;
     m_footprint = aModule;
 
@@ -88,9 +86,7 @@ DIALOG_FOOTPRINT_FP_EDITOR::DIALOG_FOOTPRINT_FP_EDITOR( FOOTPRINT_EDIT_FRAME* aP
     m_modelsGrid->PushEventHandler( new GRID_TRICKS( m_modelsGrid ) );
 
     // Show/hide columns according to the user's preference
-    wxString shownColumns;
-    m_config->Read( LibFootprintTextShownColumnsKey, &shownColumns, wxT( "0 1 2 3 4 5 6" ) );
-    m_itemsGrid->ShowHideColumns( shownColumns );
+    m_itemsGrid->ShowHideColumns( m_frame->GetSettings()->m_FootprintTextShownColumns );
 
     // Set up the 3D models grid
     wxGridCellAttr* attr = new wxGridCellAttr;
@@ -158,7 +154,8 @@ DIALOG_FOOTPRINT_FP_EDITOR::DIALOG_FOOTPRINT_FP_EDITOR( FOOTPRINT_EDIT_FRAME* aP
 
 DIALOG_FOOTPRINT_FP_EDITOR::~DIALOG_FOOTPRINT_FP_EDITOR()
 {
-    m_config->Write( LibFootprintTextShownColumnsKey, m_itemsGrid->GetShownColumns() );
+    m_frame->GetSettings()->m_FootprintTextShownColumns =
+            m_itemsGrid->GetShownColumns().ToStdString();
 
     // Prevents crash bug in wxGrid's d'tor
     m_itemsGrid->DestroyTable( m_texts );
diff --git a/pcbnew/dialogs/dialog_edit_footprint_for_fp_editor.h b/pcbnew/dialogs/dialog_edit_footprint_for_fp_editor.h
index b7a33d5b3a..43f6562b1b 100644
--- a/pcbnew/dialogs/dialog_edit_footprint_for_fp_editor.h
+++ b/pcbnew/dialogs/dialog_edit_footprint_for_fp_editor.h
@@ -39,7 +39,6 @@ class FOOTPRINT_EDIT_FRAME;
 class DIALOG_FOOTPRINT_FP_EDITOR : public DIALOG_FOOTPRINT_FP_EDITOR_BASE
 {
 private:
-    wxConfigBase*                    m_config;
     FOOTPRINT_EDIT_FRAME*            m_frame;
     MODULE*                          m_footprint;
 
diff --git a/pcbnew/dialogs/dialog_exchange_footprints.cpp b/pcbnew/dialogs/dialog_exchange_footprints.cpp
index a261f64eeb..f572fe82c1 100644
--- a/pcbnew/dialogs/dialog_exchange_footprints.cpp
+++ b/pcbnew/dialogs/dialog_exchange_footprints.cpp
@@ -24,18 +24,19 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <kicad_string.h>
-#include <pcb_edit_frame.h>
-#include <macros.h>
-#include <board_commit.h>
 #include <bitmaps.h>
+#include <board_commit.h>
 #include <class_board.h>
 #include <class_module.h>
+#include <dialog_exchange_footprints.h>
+#include <fctsys.h>
+#include <kicad_string.h>
+#include <kiway.h>
+#include <macros.h>
+#include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <project.h>
 #include <wx_html_report_panel.h>
-#include <kiway.h>
-#include <dialog_exchange_footprints.h>
 
 
 #define ID_MATCH_FP_ALL     4200
@@ -434,7 +435,7 @@ void PCB_EDIT_FRAME::Exchange_Module( MODULE* aSrc, MODULE* aDest, BOARD_COMMIT&
     aDest->SetPosition( aSrc->GetPosition() );
 
     if( aDest->GetLayer() != aSrc->GetLayer() )
-        aDest->Flip( aDest->GetPosition(), m_configSettings.m_FlipLeftRight );
+        aDest->Flip( aDest->GetPosition(), m_Settings->m_FlipLeftRight );
 
     if( aDest->GetOrientation() != aSrc->GetOrientation() )
         aDest->Rotate( aDest->GetPosition(), aSrc->GetOrientation() );
diff --git a/pcbnew/dialogs/dialog_export_idf.cpp b/pcbnew/dialogs/dialog_export_idf.cpp
index 7034446f17..1112a767d0 100644
--- a/pcbnew/dialogs/dialog_export_idf.cpp
+++ b/pcbnew/dialogs/dialog_export_idf.cpp
@@ -24,44 +24,40 @@
 
 #include <pcb_edit_frame.h>
 #include <kiface_i.h>
-#include <pcbnew.h>
 #include <class_board.h>
 #include <convert_to_biu.h>
 #include <widgets/text_ctrl_eval.h>
 #include <dialog_export_idf_base.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <confirm.h>
 
-#define OPTKEY_IDF_THOU wxT( "IDFExportThou" )
-#define OPTKEY_IDF_REF_AUTOADJ wxT( "IDFRefAutoAdj" )
-#define OPTKEY_IDF_REF_UNITS wxT( "IDFRefUnits" )
-#define OPTKEY_IDF_REF_X wxT( "IDFRefX" )
-#define OPTKEY_IDF_REF_Y wxT( "IDFRefY" )
-
 
 class DIALOG_EXPORT_IDF3: public DIALOG_EXPORT_IDF3_BASE
 {
 private:
-    wxConfigBase* m_config;
     bool   m_idfThouOpt;    // remember last preference for units in THOU
     bool   m_AutoAdjust;    // remember last Reference Point AutoAdjust setting
     int    m_RefUnits;      // remember last units for Reference Point
     double m_XRef;          // remember last X Reference Point
     double m_YRef;          // remember last Y Reference Point
 
+    PCB_EDIT_FRAME* m_parent;
+
 public:
     DIALOG_EXPORT_IDF3( PCB_EDIT_FRAME* parent ) :
-            DIALOG_EXPORT_IDF3_BASE( parent )
+            DIALOG_EXPORT_IDF3_BASE( parent ), m_parent( parent )
     {
-        m_config = Kiface().KifaceSettings();
         SetFocus();
-        m_idfThouOpt = false;
-        m_config->Read( OPTKEY_IDF_THOU, &m_idfThouOpt );
+
+        auto cfg = m_parent->GetSettings();
+
+        m_idfThouOpt = cfg->m_ExportIdf.units_mils;
         m_rbUnitSelection->SetSelection( m_idfThouOpt ? 1 : 0 );
-        m_config->Read( OPTKEY_IDF_REF_AUTOADJ, &m_AutoAdjust, false );
-        m_config->Read( OPTKEY_IDF_REF_UNITS, &m_RefUnits, 0 );
-        m_config->Read( OPTKEY_IDF_REF_X, &m_XRef, 0.0 );
-        m_config->Read( OPTKEY_IDF_REF_Y, &m_YRef, 0.0 );
+        m_AutoAdjust = cfg->m_ExportIdf.auto_adjust;
+        m_RefUnits   = cfg->m_ExportIdf.ref_units;
+        m_XRef       = cfg->m_ExportIdf.ref_x;
+        m_YRef       = cfg->m_ExportIdf.ref_y;
 
         m_cbAutoAdjustOffset->SetValue( m_AutoAdjust );
         m_cbAutoAdjustOffset->Bind( wxEVT_CHECKBOX, &DIALOG_EXPORT_IDF3::OnAutoAdjustOffset, this );
@@ -96,11 +92,14 @@ public:
     ~DIALOG_EXPORT_IDF3()
     {
         m_idfThouOpt = m_rbUnitSelection->GetSelection() == 1;
-        m_config->Write( OPTKEY_IDF_THOU, m_idfThouOpt );
-        m_config->Write( OPTKEY_IDF_REF_AUTOADJ, GetAutoAdjustOffset() );
-        m_config->Write( OPTKEY_IDF_REF_UNITS, m_IDF_RefUnitChoice->GetSelection() );
-        m_config->Write( OPTKEY_IDF_REF_X, m_IDF_Xref->GetValue() );
-        m_config->Write( OPTKEY_IDF_REF_Y, m_IDF_Yref->GetValue() );
+
+        auto cfg = m_parent->GetSettings();
+
+        cfg->m_ExportIdf.units_mils  = m_idfThouOpt;
+        cfg->m_ExportIdf.auto_adjust = m_AutoAdjust;
+        cfg->m_ExportIdf.ref_units   = m_RefUnits;
+        cfg->m_ExportIdf.ref_x       = m_XRef;
+        cfg->m_ExportIdf.ref_y       = m_YRef;
     }
 
     bool GetThouOption()
diff --git a/pcbnew/dialogs/dialog_export_step.cpp b/pcbnew/dialogs/dialog_export_step.cpp
index 78d784a846..40abb31cd7 100644
--- a/pcbnew/dialogs/dialog_export_step.cpp
+++ b/pcbnew/dialogs/dialog_export_step.cpp
@@ -31,15 +31,10 @@
 #include "reporter.h"
 #include "class_board.h"
 #include "dialog_export_step_base.h"
+#include <pcbnew_settings.h>
 #include <widgets/text_ctrl_eval.h>
 #include <wx_html_report_panel.h>
 
-#define OPTKEY_STEP_ORIGIN_OPT      "STEP_Origin_Opt"
-#define OPTKEY_STEP_UORG_UNITS      "STEP_UserOriginUnits"
-#define OPTKEY_STEP_UORG_X          "STEP_UserOriginX"
-#define OPTKEY_STEP_UORG_Y          "STEP_UserOriginY"
-#define OPTKEY_STEP_NOVIRT          "STEP_NoVirtual"
-
 
 class DIALOG_EXPORT_STEP: public DIALOG_EXPORT_STEP_BASE
 {
@@ -55,7 +50,6 @@ public:
 
 private:
     PCB_EDIT_FRAME* m_parent;
-    wxConfigBase* m_config;
     // The last preference for STEP Origin:
     STEP_ORG_OPT m_STEP_org_opt;
     bool   m_noVirtual;     // remember last preference for No Virtual Component
@@ -98,11 +92,21 @@ public:
     ~DIALOG_EXPORT_STEP()
     {
         GetOriginOption(); // Update m_STEP_org_opt member.
-        m_config->Write( OPTKEY_STEP_ORIGIN_OPT, (int)m_STEP_org_opt );
-        m_config->Write( OPTKEY_STEP_NOVIRT, m_cbRemoveVirtual->GetValue() );
-        m_config->Write( OPTKEY_STEP_UORG_UNITS, m_STEP_OrgUnitChoice->GetSelection() );
-        m_config->Write( OPTKEY_STEP_UORG_X, m_STEP_Xorg->GetValue() );
-        m_config->Write( OPTKEY_STEP_UORG_Y, m_STEP_Yorg->GetValue() );
+
+        auto cfg = m_parent->GetSettings();
+
+        cfg->m_ExportStep.origin_mode = static_cast<int>( m_STEP_org_opt );
+        cfg->m_ExportStep.origin_units = m_STEP_OrgUnitChoice->GetSelection();
+
+        double val = 0.0;
+
+        m_STEP_Xorg->GetValue().ToDouble( &val );
+        cfg->m_ExportStep.origin_x = val;
+
+        m_STEP_Yorg->GetValue().ToDouble( &val );
+        cfg->m_ExportStep.origin_y = val;
+
+        cfg->m_ExportStep.no_virtual = m_cbRemoveVirtual->GetValue();
     }
 };
 
@@ -112,7 +116,6 @@ DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aParent, const wxString&
 {
     m_parent = aParent;
     m_boardPath = aBoardPath;
-    m_config = Kiface().KifaceSettings();
     m_sdbSizerCancel->SetLabel( _( "Close" ) );
     m_sdbSizerOK->SetLabel( _( "Export" ) );
     m_sdbSizer->Layout();
@@ -131,11 +134,9 @@ DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aParent, const wxString&
 
     SetFocus();
 
-    m_STEP_org_opt = STEP_ORG_0;;
-    int tmp = STEP_ORG_0;
+    auto cfg = m_parent->GetSettings();
 
-    if( m_config->Read( OPTKEY_STEP_ORIGIN_OPT, &tmp ) )
-        m_STEP_org_opt = (STEP_ORG_OPT) tmp;
+    m_STEP_org_opt = static_cast<STEP_ORG_OPT>( cfg->m_ExportStep.origin_mode );
 
     switch( m_STEP_org_opt )
     {
@@ -146,10 +147,11 @@ DIALOG_EXPORT_STEP::DIALOG_EXPORT_STEP( PCB_EDIT_FRAME* aParent, const wxString&
         case STEP_ORG_BOARD_CENTER: m_rbBoardCenterOrigin->SetValue( true ); break;
     }
 
-    m_config->Read( OPTKEY_STEP_UORG_UNITS, &m_OrgUnits, 0 );
-    m_config->Read( OPTKEY_STEP_UORG_X, &m_XOrg, 0.0 );
-    m_config->Read( OPTKEY_STEP_UORG_Y, &m_YOrg, 0.0 );
-    m_config->Read( OPTKEY_STEP_NOVIRT, &m_noVirtual );
+    m_OrgUnits  = cfg->m_ExportStep.origin_units;
+    m_XOrg      = cfg->m_ExportStep.origin_x;
+    m_YOrg      = cfg->m_ExportStep.origin_y;
+    m_noVirtual = cfg->m_ExportStep.no_virtual;
+
     m_cbRemoveVirtual->SetValue( m_noVirtual );
 
     m_STEP_OrgUnitChoice->SetSelection( m_OrgUnits );
diff --git a/pcbnew/dialogs/dialog_export_svg.cpp b/pcbnew/dialogs/dialog_export_svg.cpp
index 41692e29fc..498de3d823 100644
--- a/pcbnew/dialogs/dialog_export_svg.cpp
+++ b/pcbnew/dialogs/dialog_export_svg.cpp
@@ -26,7 +26,8 @@
 #include <fctsys.h>
 #include <kiface_i.h>
 #include <common.h>
-#include <pcb_base_frame.h>
+#include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <wildcards_and_files_ext.h>
 #include <reporter.h>
 #include <confirm.h>
@@ -43,12 +44,12 @@
 class DIALOG_EXPORT_SVG : public DIALOG_EXPORT_SVG_BASE
 {
 public:
-    DIALOG_EXPORT_SVG( PCB_BASE_FRAME* aParent, BOARD* aBoard );
+    DIALOG_EXPORT_SVG( PCB_EDIT_FRAME* aParent, BOARD* aBoard );
     ~DIALOG_EXPORT_SVG() override;
 
 private:
     BOARD*            m_board;
-    wxConfigBase*     m_config;
+    PCB_EDIT_FRAME*   m_parent;
     LSET              m_printMaskLayer;
     // the list of existing board layers in wxCheckListBox, with the
     // board layers id:
@@ -72,24 +73,14 @@ private:
 };
 
 
-// Keys for configuration
-#define PLOTSVGMODECOLOR_KEY        wxT( "PlotSVGModeColor" )
-#define PLOTSVGMODEMIRROR_KEY       wxT( "PlotSVGModeMirror" )
-#define PLOTSVGMODEONEFILE_KEY      wxT( "PlotSVGModeOneFile" )
-#define PLOTSVGPAGESIZEOPT_KEY      wxT( "PlotSVGPageOpt" )
-#define PLOTSVGPLOT_BRD_EDGE_KEY    wxT( "PlotSVGBrdEdge" )
-#define PLOTSVG_LAYERBASE           wxT( "PlotSVGLayer_%d" )
-#define PLOTSVG_DIR_KEY             wxT( "PlotSVGDirectory" )
-
 /*
  * DIALOG_EXPORT_SVG functions
  */
-DIALOG_EXPORT_SVG::DIALOG_EXPORT_SVG( PCB_BASE_FRAME* aParent, BOARD* aBoard ) :
-    DIALOG_EXPORT_SVG_BASE( aParent ),
+DIALOG_EXPORT_SVG::DIALOG_EXPORT_SVG( PCB_EDIT_FRAME* aParent, BOARD* aBoard ) :
+    DIALOG_EXPORT_SVG_BASE( aParent ), m_parent( aParent ),
     m_lineWidth( aParent, m_penWidthLabel, m_penWidthCtrl, m_penWidthUnits, true )
 {
     m_board  = aBoard;
-    m_config = Kiface().KifaceSettings();
 
     memset( m_boxSelectLayer, 0, sizeof( m_boxSelectLayer ) );
 
@@ -115,43 +106,39 @@ DIALOG_EXPORT_SVG::~DIALOG_EXPORT_SVG()
     m_outputDirectory = m_outputDirectoryName->GetValue();
     m_outputDirectory.Replace( wxT( "\\" ), wxT( "/" ) );
 
-    if( m_config )
+    auto cfg = m_parent->GetSettings();
+
+    cfg->m_ExportSvg.black_and_white  = m_printBW;
+    cfg->m_ExportSvg.mirror           = m_printMirror;
+    cfg->m_ExportSvg.one_file         = m_oneFileOnly;
+    cfg->m_ExportSvg.plot_board_edges = m_PrintBoardEdgesCtrl->GetValue();
+    cfg->m_ExportSvg.page_size        = m_rbSvgPageSizeOpt->GetSelection();
+    cfg->m_ExportSvg.output_dir       = m_outputDirectory.ToStdString();
+
+    cfg->m_ExportSvg.layers.clear();
+
+    for( unsigned layer = 0; layer < arrayDim( m_boxSelectLayer ); ++layer )
     {
-        m_config->Write( PLOTSVG_DIR_KEY, m_outputDirectory );
-        m_config->Write( PLOTSVGMODECOLOR_KEY, m_printBW );
-        m_config->Write( PLOTSVGMODEMIRROR_KEY, m_printMirror );
-        m_config->Write( PLOTSVGMODEONEFILE_KEY, m_oneFileOnly );
-        m_config->Write( PLOTSVGPAGESIZEOPT_KEY, m_rbSvgPageSizeOpt->GetSelection() );
-        m_config->Write( PLOTSVGPLOT_BRD_EDGE_KEY, m_PrintBoardEdgesCtrl->GetValue() );
+        if( !m_boxSelectLayer[layer].first )
+            continue;
 
-        wxString layerKey;
-
-        for( unsigned layer = 0; layer < arrayDim(m_boxSelectLayer);  ++layer )
-        {
-            if( !m_boxSelectLayer[layer].first )
-                continue;
-
-            layerKey.Printf( PLOTSVG_LAYERBASE, layer );
-            m_config->Write( layerKey, m_boxSelectLayer[layer].first->IsChecked( m_boxSelectLayer[layer].second ) );
-        }
+        if( m_boxSelectLayer[layer].first->IsChecked( m_boxSelectLayer[layer].second ) )
+            cfg->m_ExportSvg.layers.push_back( m_boxSelectLayer[layer].second );
     }
 }
 
 
 void DIALOG_EXPORT_SVG::initDialog()
 {
-    if( m_config )
-    {
-        m_config->Read( PLOTSVG_DIR_KEY, &m_outputDirectory, wxEmptyString );
-        m_config->Read( PLOTSVGMODECOLOR_KEY, &m_printBW, false );
-        long ltmp;
-        m_config->Read( PLOTSVGPAGESIZEOPT_KEY, &ltmp, 0 );
-        m_rbSvgPageSizeOpt->SetSelection( ltmp );
-        m_config->Read( PLOTSVGMODEMIRROR_KEY, &m_printMirror, false );
-        m_config->Read( PLOTSVGMODEONEFILE_KEY, &m_oneFileOnly, false);
-        m_config->Read( PLOTSVGPLOT_BRD_EDGE_KEY, &ltmp, 1 );
-        m_PrintBoardEdgesCtrl->SetValue( ltmp );
-    }
+    auto cfg = m_parent->GetSettings();
+
+    m_printBW         = cfg->m_ExportSvg.black_and_white;
+    m_printMirror     = cfg->m_ExportSvg.mirror;
+    m_oneFileOnly     = cfg->m_ExportSvg.one_file;
+    m_outputDirectory = cfg->m_ExportSvg.output_dir;
+
+    m_rbSvgPageSizeOpt->SetSelection( cfg->m_ExportSvg.page_size );
+    m_PrintBoardEdgesCtrl->SetValue( cfg->m_ExportSvg.plot_board_edges );
 
     m_outputDirectoryName->SetValue( m_outputDirectory );
 
@@ -177,15 +164,9 @@ void DIALOG_EXPORT_SVG::initDialog()
             m_boxSelectLayer[layer] = std::make_pair( m_TechnicalLayersList, checkIndex );
         }
 
-        if( m_config )
-        {
-            wxString layerKey;
-            layerKey.Printf( PLOTSVG_LAYERBASE, layer );
-            bool option;
-
-            if( m_config && m_config->Read( layerKey, &option ) )
-                m_boxSelectLayer[layer].first->Check( checkIndex, option );
-        }
+        if( std::find( cfg->m_ExportSvg.layers.begin(), cfg->m_ExportSvg.layers.end(), layer ) !=
+            cfg->m_ExportSvg.layers.end() )
+            m_boxSelectLayer[layer].first->Check( checkIndex, true );
     }
 }
 
@@ -361,7 +342,7 @@ void DIALOG_EXPORT_SVG::OnButtonPlot( wxCommandEvent& event )
 }
 
 
-bool InvokeExportSVG( PCB_BASE_FRAME* aCaller, BOARD* aBoard )
+bool InvokeExportSVG( PCB_EDIT_FRAME* aCaller, BOARD* aBoard )
 {
     DIALOG_EXPORT_SVG dlg( aCaller, aBoard );
 
diff --git a/pcbnew/dialogs/dialog_export_vrml.cpp b/pcbnew/dialogs/dialog_export_vrml.cpp
index b260134632..2d1ff32020 100644
--- a/pcbnew/dialogs/dialog_export_vrml.cpp
+++ b/pcbnew/dialogs/dialog_export_vrml.cpp
@@ -33,6 +33,7 @@
 #include <fctsys.h>
 #include <kiface_i.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <pcbnew.h>
 
 
@@ -41,19 +42,11 @@
  */
 #include <dialog_export_vrml_base.h> // the wxFormBuilder header file
 
-#define OPTKEY_OUTPUT_UNIT wxT( "VrmlExportUnit" )
-#define OPTKEY_3DFILES_OPT wxT( "VrmlExportCopyFiles" )
-#define OPTKEY_USE_RELATIVE_PATHS wxT( "VrmlUseRelativePaths" )
-#define OPTKEY_USE_PLAIN_PCB wxT( "VrmlUsePlainPCB" )
-#define OPTKEY_VRML_REF_UNITS wxT( "VrmlRefUnits" )
-#define OPTKEY_VRML_REF_X wxT( "VrmlRefX" )
-#define OPTKEY_VRML_REF_Y wxT( "VrmlRefY" )
-
 
 class DIALOG_EXPORT_3DFILE : public DIALOG_EXPORT_3DFILE_BASE
 {
 private:
-    wxConfigBase*   m_config;
+    PCB_EDIT_FRAME* m_parent;
     int             m_unitsOpt;             // Remember last units option
     bool            m_copy3DFilesOpt;       // Remember last copy model files option
     bool            m_useRelativePathsOpt;  // Remember last use absolute paths option
@@ -64,17 +57,20 @@ private:
 
 public:
     DIALOG_EXPORT_3DFILE( PCB_EDIT_FRAME* parent ) :
-        DIALOG_EXPORT_3DFILE_BASE( parent )
+        DIALOG_EXPORT_3DFILE_BASE( parent ), m_parent( parent )
     {
-        m_config = Kiface().KifaceSettings();
         m_filePicker->SetFocus();
-        m_config->Read( OPTKEY_OUTPUT_UNIT, &m_unitsOpt, 1 );
-        m_config->Read( OPTKEY_3DFILES_OPT, &m_copy3DFilesOpt, false );
-        m_config->Read( OPTKEY_USE_RELATIVE_PATHS, &m_useRelativePathsOpt, false );
-        m_config->Read( OPTKEY_USE_PLAIN_PCB, &m_usePlainPCBOpt, false );
-        m_config->Read( OPTKEY_VRML_REF_UNITS, &m_RefUnits, 0 );
-        m_config->Read( OPTKEY_VRML_REF_X, &m_XRef, 0.0 );
-        m_config->Read( OPTKEY_VRML_REF_Y, &m_YRef, 0.0 );
+
+        auto cfg = m_parent->GetSettings();
+
+        m_unitsOpt            = cfg->m_ExportVrml.units;
+        m_copy3DFilesOpt      = cfg->m_ExportVrml.copy_3d_models;
+        m_useRelativePathsOpt = cfg->m_ExportVrml.use_relative_paths;
+        m_usePlainPCBOpt      = cfg->m_ExportVrml.use_plain_pcb;
+        m_RefUnits            = cfg->m_ExportVrml.ref_units;
+        m_XRef                = cfg->m_ExportVrml.ref_x;
+        m_YRef                = cfg->m_ExportVrml.ref_y;
+
         m_rbSelectUnits->SetSelection( m_unitsOpt );
         m_cbCopyFiles->SetValue( m_copy3DFilesOpt );
         m_cbUseRelativePaths->SetValue( m_useRelativePathsOpt );
@@ -99,13 +95,21 @@ public:
     {
         m_unitsOpt = GetUnits();
         m_copy3DFilesOpt = GetCopyFilesOption();
-        m_config->Write( OPTKEY_OUTPUT_UNIT, m_unitsOpt );
-        m_config->Write( OPTKEY_3DFILES_OPT, m_copy3DFilesOpt );
-        m_config->Write( OPTKEY_USE_RELATIVE_PATHS, m_useRelativePathsOpt );
-        m_config->Write( OPTKEY_USE_PLAIN_PCB, m_usePlainPCBOpt );
-        m_config->Write( OPTKEY_VRML_REF_UNITS, m_VRML_RefUnitChoice->GetSelection() );
-        m_config->Write( OPTKEY_VRML_REF_X, m_VRML_Xref->GetValue() );
-        m_config->Write( OPTKEY_VRML_REF_Y, m_VRML_Yref->GetValue() );
+
+        auto cfg = m_parent->GetSettings();
+
+        cfg->m_ExportVrml.units              = m_unitsOpt;
+        cfg->m_ExportVrml.copy_3d_models     = m_copy3DFilesOpt;
+        cfg->m_ExportVrml.use_relative_paths = m_useRelativePathsOpt;
+        cfg->m_ExportVrml.use_plain_pcb      = m_usePlainPCBOpt;
+        cfg->m_ExportVrml.ref_units          = m_VRML_RefUnitChoice->GetSelection();
+
+        double val = 0.0;
+        m_VRML_Xref->GetValue().ToDouble( &val );
+        cfg->m_ExportVrml.ref_x = val;
+
+        m_VRML_Yref->GetValue().ToDouble( &val );
+        cfg->m_ExportVrml.ref_y = val;
     };
 
     void SetSubdir( const wxString & aDir )
diff --git a/pcbnew/dialogs/dialog_footprint_wizard_list.cpp b/pcbnew/dialogs/dialog_footprint_wizard_list.cpp
index bbe91d976f..7ef7dd69b5 100644
--- a/pcbnew/dialogs/dialog_footprint_wizard_list.cpp
+++ b/pcbnew/dialogs/dialog_footprint_wizard_list.cpp
@@ -29,6 +29,9 @@
 #include <wx/grid.h>
 
 #include <pcbnew.h>
+#include <pcbnew_settings.h>
+#include <pgm_base.h>
+#include <settings/settings_manager.h>
 #include <kiface_i.h>
 #include <dialog_footprint_wizard_list.h>
 #include <footprint_wizard_frame.h>
@@ -49,22 +52,18 @@ enum FPGeneratorRowNames
     FP_GEN_ROW_DESCR,
 };
 
-#define FPWIZARTDLIST_HEIGHT_KEY wxT( "FpWizardListHeight" )
-#define FPWIZARTDLIST_WIDTH_KEY  wxT( "FpWizardListWidth" )
 
 DIALOG_FOOTPRINT_WIZARD_LIST::DIALOG_FOOTPRINT_WIZARD_LIST( wxWindow* aParent )
     : DIALOG_FOOTPRINT_WIZARD_LIST_BASE( aParent )
 {
-    m_config = Kiface().KifaceSettings();
     initLists();
 
-    if( m_config )
-    {
-        wxSize size;
-        m_config->Read( FPWIZARTDLIST_WIDTH_KEY, &size.x, -1 );
-        m_config->Read( FPWIZARTDLIST_HEIGHT_KEY, &size.y, -1 );
-        SetSize( size );
-    }
+    auto cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
+
+    wxSize size;
+    size.x = cfg->m_FootprintWizardList.width;
+    size.y = cfg->m_FootprintWizardList.height;
+    SetSize( size );
 
     m_sdbSizerOK->SetDefault();
     FinishDialogSettings();
@@ -75,10 +74,12 @@ DIALOG_FOOTPRINT_WIZARD_LIST::DIALOG_FOOTPRINT_WIZARD_LIST( wxWindow* aParent )
 
 DIALOG_FOOTPRINT_WIZARD_LIST::~DIALOG_FOOTPRINT_WIZARD_LIST()
 {
-    if( m_config && !IsIconized() )
+    if( !IsIconized() )
     {
-        m_config->Write( FPWIZARTDLIST_WIDTH_KEY, GetSize().x );
-        m_config->Write( FPWIZARTDLIST_HEIGHT_KEY, GetSize().y );
+        auto cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
+
+        cfg->m_FootprintWizardList.width  = GetSize().x;
+        cfg->m_FootprintWizardList.height = GetSize().y;
     }
 }
 
diff --git a/pcbnew/dialogs/dialog_footprint_wizard_list.h b/pcbnew/dialogs/dialog_footprint_wizard_list.h
index b143c2dc1d..1e1e84ae45 100644
--- a/pcbnew/dialogs/dialog_footprint_wizard_list.h
+++ b/pcbnew/dialogs/dialog_footprint_wizard_list.h
@@ -32,7 +32,6 @@ class DIALOG_FOOTPRINT_WIZARD_LIST: public DIALOG_FOOTPRINT_WIZARD_LIST_BASE
 {
 private:
     FOOTPRINT_WIZARD* m_footprintWizard;    ///< The selected python script wizard
-    wxConfigBase*     m_config;
 
 public:
     DIALOG_FOOTPRINT_WIZARD_LIST( wxWindow * aParent );
diff --git a/pcbnew/dialogs/dialog_gendrill.cpp b/pcbnew/dialogs/dialog_gendrill.cpp
index 0b6b1dcd51..1c74b8c0b7 100644
--- a/pcbnew/dialogs/dialog_gendrill.cpp
+++ b/pcbnew/dialogs/dialog_gendrill.cpp
@@ -27,6 +27,7 @@
 #include <confirm.h>
 #include <pcbnew.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <pcbplot.h>
 #include <gendrill_Excellon_writer.h>
 #include <gendrill_gerber_writer.h>
@@ -41,16 +42,6 @@
 #include <wx/stdpaths.h>
 
 
-// Keywords for read and write parameters in project config
-#define ZerosFormatKey          wxT( "DrillZerosFormat" )
-#define MirrorKey               wxT( "DrillMirrorYOpt" )
-#define MinimalHeaderKey        wxT( "DrillMinHeader" )
-#define MergePTHNPTHKey         wxT( "DrillMergePTHNPTH" )
-#define UnitDrillInchKey        wxT( "DrillUnit" )
-#define DrillMapFileTypeKey     wxT( "DrillMapFileType" )
-#define DrillFileFormatKey      wxT( "DrillFileType" )
-#define OvalHolesRouteModeKey   wxT( "OvalHolesRouteMode" )
-
 // list of allowed precision for EXCELLON files, for integer format:
 // Due to difference between inches and mm,
 // there are 2 precision values, one for inches and one for metric
@@ -76,7 +67,6 @@ DIALOG_GENDRILL::DIALOG_GENDRILL(  PCB_EDIT_FRAME* aPcbEditFrame, wxWindow* aPar
 {
     m_pcbEditFrame = aPcbEditFrame;
     m_board  = m_pcbEditFrame->GetBoard();
-    m_config = Kiface().KifaceSettings();
     m_plotOpts = m_pcbEditFrame->GetPlotSettings();
 
     // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
@@ -110,15 +100,18 @@ DIALOG_GENDRILL::~DIALOG_GENDRILL()
 
 void DIALOG_GENDRILL::initDialog()
 {
-    m_config->Read( ZerosFormatKey, &m_ZerosFormat );
-    m_config->Read( MirrorKey, &m_Mirror );
-    m_config->Read( MergePTHNPTHKey, &m_Merge_PTH_NPTH );
-    m_config->Read( MinimalHeaderKey, &m_MinimalHeader );
-    m_config->Read( UnitDrillInchKey, &m_UnitDrillIsInch );
+    auto cfg = m_pcbEditFrame->GetSettings();
+
+    m_Merge_PTH_NPTH           = cfg->m_GenDrill.merge_pth_npth;
+    m_MinimalHeader            = cfg->m_GenDrill.minimal_header;
+    m_Mirror                   = cfg->m_GenDrill.mirror;
+    m_UnitDrillIsInch          = cfg->m_GenDrill.unit_drill_is_inch;
+    m_UseRouteModeForOvalHoles = cfg->m_GenDrill.use_route_for_oval_holes;
+    m_drillFileType            = cfg->m_GenDrill.drill_file_type;
+    m_mapFileType              = cfg->m_GenDrill.map_file_type;
+    m_ZerosFormat              = cfg->m_GenDrill.zeros_format;
+
     m_drillOriginIsAuxAxis = m_plotOpts.GetUseAuxOrigin();
-    m_config->Read( DrillMapFileTypeKey, &m_mapFileType );
-    m_config->Read( DrillFileFormatKey, &m_drillFileType );
-    m_config->Read( OvalHolesRouteModeKey, &m_UseRouteModeForOvalHoles );
 
     InitDisplayParams();
 }
@@ -243,14 +236,16 @@ void DIALOG_GENDRILL::UpdateConfig()
 {
     UpdateDrillParams();
 
-    m_config->Write( ZerosFormatKey, m_ZerosFormat );
-    m_config->Write( MirrorKey, m_Mirror );
-    m_config->Write( MergePTHNPTHKey, m_Merge_PTH_NPTH );
-    m_config->Write( MinimalHeaderKey, m_MinimalHeader );
-    m_config->Write( UnitDrillInchKey, m_UnitDrillIsInch );
-    m_config->Write( DrillMapFileTypeKey, m_mapFileType );
-    m_config->Write( DrillFileFormatKey, m_drillFileType );
-    m_config->Write( OvalHolesRouteModeKey, m_UseRouteModeForOvalHoles );
+    auto cfg = m_pcbEditFrame->GetSettings();
+
+    cfg->m_GenDrill.merge_pth_npth           = m_Merge_PTH_NPTH;
+    cfg->m_GenDrill.minimal_header           = m_MinimalHeader;
+    cfg->m_GenDrill.mirror                   = m_Mirror;
+    cfg->m_GenDrill.unit_drill_is_inch       = m_UnitDrillIsInch;
+    cfg->m_GenDrill.use_route_for_oval_holes = m_UseRouteModeForOvalHoles;
+    cfg->m_GenDrill.drill_file_type          = m_drillFileType;
+    cfg->m_GenDrill.map_file_type            = m_mapFileType;
+    cfg->m_GenDrill.zeros_format             = m_ZerosFormat;
 }
 
 
diff --git a/pcbnew/dialogs/dialog_gendrill.h b/pcbnew/dialogs/dialog_gendrill.h
index 377d663563..ad9ce0c365 100644
--- a/pcbnew/dialogs/dialog_gendrill.h
+++ b/pcbnew/dialogs/dialog_gendrill.h
@@ -57,7 +57,6 @@ public:
 
 private:
     PCB_EDIT_FRAME*  m_pcbEditFrame;
-    wxConfigBase*    m_config;
     BOARD*           m_board;
     PCB_PLOT_PARAMS  m_plotOpts;
     bool             m_drillOriginIsAuxAxis;     // Axis selection (main / auxiliary)
diff --git a/pcbnew/dialogs/dialog_get_footprint_by_name.h b/pcbnew/dialogs/dialog_get_footprint_by_name.h
index 24cd1d986e..96238d3f81 100644
--- a/pcbnew/dialogs/dialog_get_footprint_by_name.h
+++ b/pcbnew/dialogs/dialog_get_footprint_by_name.h
@@ -30,6 +30,7 @@
 #define DIALOG_GET_FOOTPRINT_BY_NAME_H
 
 #include <dialog_get_footprint_by_name_base.h>
+#include <pcb_base_frame.h>
 
 /**
  * DIALOG_GET_FOOTPRINT_BY_NAME is a helper dialog to select a footprint by its reference
diff --git a/pcbnew/dialogs/dialog_keepout_area_properties.cpp b/pcbnew/dialogs/dialog_keepout_area_properties.cpp
index 06f1413320..cde2a55eca 100644
--- a/pcbnew/dialogs/dialog_keepout_area_properties.cpp
+++ b/pcbnew/dialogs/dialog_keepout_area_properties.cpp
@@ -27,6 +27,7 @@
 #include <kiface_i.h>
 #include <confirm.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <footprint_edit_frame.h>
 #include <class_zone.h>
 #include <zones.h>
@@ -45,7 +46,6 @@ public:
 
 private:
     PCB_BASE_FRAME* m_parent;
-    wxConfigBase*   m_config;               ///< Current config
     ZONE_SETTINGS   m_zonesettings;         ///< the working copy of zone settings
     ZONE_SETTINGS*  m_ptr;                  ///< the pointer to the zone settings
                                             ///< of the zone to edit
@@ -71,7 +71,6 @@ DIALOG_KEEPOUT_AREA_PROPERTIES::DIALOG_KEEPOUT_AREA_PROPERTIES( PCB_BASE_FRAME*
     DIALOG_KEEPOUT_AREA_PROPERTIES_BASE( aParent )
 {
     m_parent = aParent;
-    m_config = Kiface().KifaceSettings();
 
     m_ptr = aSettings;
     m_zonesettings = *aSettings;
@@ -176,8 +175,8 @@ bool DIALOG_KEEPOUT_AREA_PROPERTIES::TransferDataFromWindow()
         break;
     }
 
-    if( m_config )
-        m_config->Write( ZONE_NET_OUTLINES_STYLE_KEY, (long) m_zonesettings.m_Zone_HatchingStyle );
+    auto cfg = m_parent->GetSettings();
+    cfg->m_Zones.hatching_style = static_cast<int>( m_zonesettings.m_Zone_HatchingStyle );
 
     m_zonesettings.m_Zone_45_Only = m_cbConstrainCtrl->GetValue();
     m_zonesettings.m_ZonePriority = 0;  // for a keepout, this param is not used.
diff --git a/pcbnew/dialogs/dialog_netlist.cpp b/pcbnew/dialogs/dialog_netlist.cpp
index 8489a5fffd..567b48924d 100644
--- a/pcbnew/dialogs/dialog_netlist.cpp
+++ b/pcbnew/dialogs/dialog_netlist.cpp
@@ -28,6 +28,7 @@
 #include <macros.h>
 #include <html_messagebox.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <reporter.h>
 #include <bitmaps.h>
 #include <drc/drc.h>
@@ -43,11 +44,6 @@
 
 #include <wx_html_report_panel.h>
 
-#define NETLIST_FILTER_MESSAGES_KEY wxT("NetlistReportFilterMsg")
-#define NETLIST_UPDATEFOOTPRINTS_KEY wxT("NetlistUpdateFootprints")
-#define NETLIST_DELETESHORTINGTRACKS_KEY wxT("NetlistDeleteShortingTracks")
-#define NETLIST_DELETEEXTRAFOOTPRINTS_KEY wxT("NetlistDeleteExtraFootprints")
-#define NETLIST_DELETESINGLEPADNETS_KEY wxT("NetlistDeleteSinglePadNets")
 
 void PCB_EDIT_FRAME::InstallNetlistFrame()
 {
@@ -70,19 +66,20 @@ DIALOG_NETLIST::DIALOG_NETLIST( PCB_EDIT_FRAME* aParent, wxString& aNetlistFullF
       m_initialized( false ),
       m_runDragCommand( false )
 {
-    m_config = Kiface().KifaceSettings();
-
     m_NetlistFilenameCtrl->SetValue( m_netlistPath );
     m_browseButton->SetBitmap( KiBitmap( folder_xpm ) );
 
-    m_cbUpdateFootprints->SetValue( m_config->Read( NETLIST_UPDATEFOOTPRINTS_KEY, 0l ) );
-    m_cbDeleteShortingTracks->SetValue( m_config->Read( NETLIST_DELETESHORTINGTRACKS_KEY, 0l ) );
-    m_cbDeleteExtraFootprints->SetValue( m_config->Read( NETLIST_DELETEEXTRAFOOTPRINTS_KEY, 0l ) );
-    m_cbDeleteSinglePadNets->SetValue( m_config->Read( NETLIST_DELETESINGLEPADNETS_KEY, 0l ) );
+    auto cfg = m_parent->GetSettings();
+
+    m_cbUpdateFootprints->SetValue( cfg->m_NetlistDialog.update_footprints );
+    m_cbDeleteShortingTracks->SetValue( cfg->m_NetlistDialog.delete_shorting_tracks );
+    m_cbDeleteExtraFootprints->SetValue( cfg->m_NetlistDialog.delete_extra_footprints );
+    m_cbDeleteSinglePadNets->SetValue( cfg->m_NetlistDialog.delete_single_pad_nets );
+
     m_cbWarnNoNetPad->SetValue( m_warnForNoNetPads );
 
     m_MessageWindow->SetLabel( _("Changes To Be Applied") );
-    m_MessageWindow->SetVisibleSeverities( m_config->Read( NETLIST_FILTER_MESSAGES_KEY, -1l ) );
+    m_MessageWindow->SetVisibleSeverities( cfg->m_NetlistDialog.report_filter );
 
     // We use a sdbSizer to get platform-dependent ordering of the action buttons, but
     // that requires us to correct the button labels here.
@@ -102,11 +99,13 @@ DIALOG_NETLIST::~DIALOG_NETLIST()
 {
     m_warnForNoNetPads = m_cbWarnNoNetPad->GetValue();
 
-    m_config->Write( NETLIST_UPDATEFOOTPRINTS_KEY, m_cbUpdateFootprints->GetValue() );
-    m_config->Write( NETLIST_DELETESHORTINGTRACKS_KEY, m_cbDeleteShortingTracks->GetValue() );
-    m_config->Write( NETLIST_DELETEEXTRAFOOTPRINTS_KEY, m_cbDeleteExtraFootprints->GetValue() );
-    m_config->Write( NETLIST_DELETESINGLEPADNETS_KEY, m_cbDeleteSinglePadNets->GetValue() );
-    m_config->Write( NETLIST_FILTER_MESSAGES_KEY, (long) m_MessageWindow->GetVisibleSeverities() );
+    auto cfg = m_parent->GetSettings();
+
+    cfg->m_NetlistDialog.report_filter           = m_cbUpdateFootprints->GetValue();
+    cfg->m_NetlistDialog.update_footprints       = m_cbDeleteShortingTracks->GetValue();
+    cfg->m_NetlistDialog.delete_shorting_tracks  = m_cbDeleteExtraFootprints->GetValue();
+    cfg->m_NetlistDialog.delete_extra_footprints = m_cbDeleteSinglePadNets->GetValue();
+    cfg->m_NetlistDialog.delete_single_pad_nets  = m_MessageWindow->GetVisibleSeverities();
 
     if( m_runDragCommand )
     {
diff --git a/pcbnew/dialogs/dialog_netlist.h b/pcbnew/dialogs/dialog_netlist.h
index d836152a55..cbfb9d8e98 100644
--- a/pcbnew/dialogs/dialog_netlist.h
+++ b/pcbnew/dialogs/dialog_netlist.h
@@ -40,7 +40,6 @@ class DIALOG_NETLIST : public DIALOG_NETLIST_BASE
 private:
     PCB_EDIT_FRAME* m_parent;
     wxString&       m_netlistPath;
-    wxConfigBase*   m_config;
     bool            m_initialized;
     bool            m_runDragCommand;
     static bool     m_warnForNoNetPads;
diff --git a/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp b/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp
index efb5b5baf6..dfa3fa9f4f 100644
--- a/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp
+++ b/pcbnew/dialogs/dialog_non_copper_zones_properties.cpp
@@ -30,6 +30,7 @@
 #include <kiface_i.h>
 #include <confirm.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <widgets/unit_binder.h>
 #include <class_zone.h>
 #include <zones.h>
@@ -259,10 +260,8 @@ bool DIALOG_NON_COPPER_ZONES_EDITOR::TransferDataFromWindow()
     m_settings.m_HatchFillTypeSmoothingLevel = m_spinCtrlSmoothLevel->GetValue();
     m_settings.m_HatchFillTypeSmoothingValue = m_spinCtrlSmoothValue->GetValue();
 
-    wxConfigBase* cfg = Kiface().KifaceSettings();
-    wxASSERT( cfg );
-
-    cfg->Write( ZONE_NET_OUTLINES_STYLE_KEY, (long) m_settings.m_Zone_HatchingStyle );
+    auto cfg = m_parent->GetSettings();
+    cfg->m_Zones.hatching_style = static_cast<int>( m_settings.m_Zone_HatchingStyle );
 
     m_settings.m_Zone_45_Only = m_ConstrainOpt->GetValue();
 
diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp
index d9464800c3..9174116668 100644
--- a/pcbnew/dialogs/dialog_pad_properties.cpp
+++ b/pcbnew/dialogs/dialog_pad_properties.cpp
@@ -24,22 +24,23 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <gal/graphics_abstraction_layer.h>
-#include <view/view_controls.h>
-#include <confirm.h>
-#include <pcbnew.h>
-#include <pcb_base_frame.h>
 #include <base_units.h>
-#include <board_commit.h>
 #include <bitmaps.h>
+#include <board_commit.h>
 #include <class_board.h>
 #include <class_module.h>
-#include <pcb_painter.h>
-#include <widgets/net_selector.h>
-#include <dialog_pad_properties.h>
+#include <confirm.h>
+#include <convert_basic_shapes_to_polygon.h> // for enum RECT_CHAMFER_POSITIONS definition
 #include <dialog_pad_properties.h>
+#include <gal/graphics_abstraction_layer.h>
 #include <html_messagebox.h>
-#include <convert_basic_shapes_to_polygon.h>    // for enum RECT_CHAMFER_POSITIONS definition
+#include <pcb_base_frame.h>
+#include <pcb_painter.h>
+#include <pcbnew.h>
+#include <pcbnew_settings.h>
+#include <settings/color_settings.h>
+#include <view/view_controls.h>
+#include <widgets/net_selector.h>
 
 #include <advanced_config.h>    // for pad property feature management
 
@@ -245,7 +246,7 @@ void DIALOG_PAD_PROPERTIES::prepareCanvas()
                                                VECTOR2D( m_dummyPad->GetPosition() ) );
     m_axisOrigin->SetDrawAtZero( true );
 
-    m_panelShowPadGal->UseColorScheme( &m_parent->Settings().Colors() );
+    m_panelShowPadGal->UpdateColors();
     m_panelShowPadGal->SwitchBackend( m_parent->GetCanvas()->GetBackend() );
     m_panelShowPadGal->SetStealsFocus( false );
 
@@ -286,10 +287,10 @@ void DIALOG_PAD_PROPERTIES::OnPaintShowPanel( wxPaintEvent& event )
     COLOR4D color = COLOR4D::BLACK;
 
     if( m_dummyPad->GetLayerSet()[F_Cu] )
-        color = m_parent->Settings().Colors().GetItemColor( LAYER_PAD_FR );
+        color = m_parent->ColorSettings()->GetColor( LAYER_PAD_FR );
 
     if( m_dummyPad->GetLayerSet()[B_Cu] )
-        color = color.LegacyMix( m_parent->Settings().Colors().GetItemColor( LAYER_PAD_BK ) );
+        color = color.LegacyMix( m_parent->ColorSettings()->GetColor( LAYER_PAD_BK ) );
 
     // What could happen: the pad color is *actually* black, or no copper was selected
     if( color == BLACK )
diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp
index 90f05f87c9..2403ccffa8 100644
--- a/pcbnew/dialogs/dialog_plot.cpp
+++ b/pcbnew/dialogs/dialog_plot.cpp
@@ -26,6 +26,7 @@
 #include <plotter.h>
 #include <confirm.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <pcbplot.h>
 #include <gerber_jobfile_writer.h>
 #include <reporter.h>
@@ -49,7 +50,6 @@ DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aParent ) :
     m_trackWidthCorrection( aParent, m_widthAdjustLabel, m_widthAdjustCtrl, m_widthAdjustUnits, true )
 {
     SetName( DLG_WINDOW_NAME );
-    m_config = Kiface().KifaceSettings();
     m_plotOpts = aParent->GetPlotSettings();
     init_Dialog();
 
@@ -72,19 +72,17 @@ void DIALOG_PLOT::init_Dialog()
     BOARD*      board = m_parent->GetBoard();
     wxFileName  fileName;
 
-    m_config->Read( OPTKEY_PLOT_X_FINESCALE_ADJ, &m_XScaleAdjust );
-    m_config->Read( OPTKEY_PLOT_Y_FINESCALE_ADJ, &m_YScaleAdjust );
+    auto cfg = m_parent->GetSettings();
 
-    bool checkZones;
-    m_config->Read( OPTKEY_PLOT_CHECK_ZONES, &checkZones, true );
-    m_zoneFillCheck->SetValue( checkZones );
+    m_XScaleAdjust = cfg->m_Plot.fine_scale_x;
+    m_YScaleAdjust = cfg->m_Plot.fine_scale_y;
+
+    m_zoneFillCheck->SetValue( cfg->m_Plot.check_zones_before_plotting );
 
     m_browseButton->SetBitmap( KiBitmap( folder_xpm ) );
 
     // m_PSWidthAdjust is stored in mm in user config
-    double dtmp;
-    m_config->Read( CONFIG_PS_FINEWIDTH_ADJ, &dtmp, 0 );
-    m_PSWidthAdjust = KiROUND( dtmp * IU_PER_MM );
+    m_PSWidthAdjust = KiROUND( cfg->m_Plot.ps_fine_width_adjust * IU_PER_MM );
 
     // The reasonable width correction value must be in a range of
     // [-(MinTrackWidth-1), +(MinClearanceValue-1)] decimils.
@@ -642,8 +640,6 @@ void DIALOG_PLOT::applyPlotSettings()
         reporter.Report( msg, REPORTER::RPT_INFO );
     }
 
-    ConfigBaseWriteDouble( m_config, OPTKEY_PLOT_X_FINESCALE_ADJ, m_XScaleAdjust );
-
     // Y scale
     msg = m_fineAdjustYCtrl->GetValue();
     msg.ToDouble( &tmpDouble );
@@ -656,9 +652,12 @@ void DIALOG_PLOT::applyPlotSettings()
         reporter.Report( msg, REPORTER::RPT_INFO );
     }
 
-    ConfigBaseWriteDouble( m_config, OPTKEY_PLOT_Y_FINESCALE_ADJ, m_YScaleAdjust );
+    auto cfg = m_parent->GetSettings();
 
-    m_config->Write( OPTKEY_PLOT_CHECK_ZONES, m_zoneFillCheck->GetValue() );
+    cfg->m_Plot.fine_scale_x = m_XScaleAdjust;
+    cfg->m_Plot.fine_scale_y = m_YScaleAdjust;
+
+    cfg->m_Plot.check_zones_before_plotting = m_zoneFillCheck->GetValue();
 
     // PS Width correction
     if( !setInt( &m_PSWidthAdjust, m_trackWidthCorrection.GetValue(),
@@ -675,8 +674,7 @@ void DIALOG_PLOT::applyPlotSettings()
     }
 
     // Store m_PSWidthAdjust in mm in user config
-    ConfigBaseWriteDouble( m_config, CONFIG_PS_FINEWIDTH_ADJ,
-                           (double)m_PSWidthAdjust / IU_PER_MM );
+    cfg->m_Plot.ps_fine_width_adjust = Iu2Millimeter( m_PSWidthAdjust );
 
     tempOptions.SetFormat( getPlotFormat() );
 
diff --git a/pcbnew/dialogs/dialog_plot.h b/pcbnew/dialogs/dialog_plot.h
index 794391aeb0..780df8efb4 100644
--- a/pcbnew/dialogs/dialog_plot.h
+++ b/pcbnew/dialogs/dialog_plot.h
@@ -44,7 +44,6 @@ public:
 
 private:
     PCB_EDIT_FRAME*     m_parent;
-    wxConfigBase*       m_config;
     LSEQ                m_layerList;                // List to hold CheckListBox layer numbers
     double              m_XScaleAdjust;             // X scale factor adjust to compensate
                                                     // plotter X scaling error
diff --git a/pcbnew/dialogs/dialog_update_pcb.cpp b/pcbnew/dialogs/dialog_update_pcb.cpp
index dd10266ad2..ee78cc59f6 100644
--- a/pcbnew/dialogs/dialog_update_pcb.cpp
+++ b/pcbnew/dialogs/dialog_update_pcb.cpp
@@ -27,6 +27,7 @@
 
 #include <common.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <dialog_update_pcb.h>
 #include <wx_html_report_panel.h>
 #include <netlist_reader/pcb_netlist.h>
@@ -43,11 +44,6 @@
 
 using namespace std::placeholders;
 
-#define NETLIST_FILTER_MESSAGES_KEY wxT("NetlistReportFilterMsg")
-#define NETLIST_UPDATEFOOTPRINTS_KEY wxT("NetlistUpdateFootprints")
-#define NETLIST_DELETESHORTINGTRACKS_KEY wxT("NetlistDeleteShortingTracks")
-#define NETLIST_DELETEEXTRAFOOTPRINTS_KEY wxT("NetlistDeleteExtraFootprints")
-#define NETLIST_DELETESINGLEPADNETS_KEY wxT("NetlistDeleteSinglePadNets")
 
 bool DIALOG_UPDATE_PCB::m_warnForNoNetPads = false;
 
@@ -58,18 +54,18 @@ DIALOG_UPDATE_PCB::DIALOG_UPDATE_PCB( PCB_EDIT_FRAME* aParent, NETLIST* aNetlist
     m_netlist( aNetlist ),
     m_initialized( false )
 {
-    m_config = Kiface().KifaceSettings();
+    auto cfg = m_frame->GetSettings();
 
-    m_cbUpdateFootprints->SetValue( m_config->Read( NETLIST_UPDATEFOOTPRINTS_KEY, 0l ) );
-    m_cbDeleteExtraFootprints->SetValue( m_config->Read( NETLIST_DELETEEXTRAFOOTPRINTS_KEY, 0l ) );
-    m_cbDeleteSinglePadNets->SetValue( m_config->Read( NETLIST_DELETESINGLEPADNETS_KEY, 0l ) );
+    m_cbUpdateFootprints->SetValue( cfg->m_NetlistDialog.update_footprints );
+    m_cbDeleteExtraFootprints->SetValue( cfg->m_NetlistDialog.delete_extra_footprints );
+    m_cbDeleteSinglePadNets->SetValue( cfg->m_NetlistDialog.delete_single_pad_nets );
     m_cbWarnNoNetPad->SetValue( m_warnForNoNetPads );
 
     m_messagePanel->SetLabel( _("Changes To Be Applied") );
     m_messagePanel->SetLazyUpdate( true );
     m_netlist->SortByReference();
 
-    m_messagePanel->SetVisibleSeverities( m_config->Read( NETLIST_FILTER_MESSAGES_KEY, -1l ) );
+    m_messagePanel->SetVisibleSeverities( cfg->m_NetlistDialog.report_filter );
 
     m_messagePanel->GetSizer()->SetSizeHints( this );
 
@@ -91,10 +87,12 @@ DIALOG_UPDATE_PCB::~DIALOG_UPDATE_PCB()
 {
     m_warnForNoNetPads = m_cbWarnNoNetPad->GetValue();
 
-    m_config->Write( NETLIST_UPDATEFOOTPRINTS_KEY, m_cbUpdateFootprints->GetValue() );
-    m_config->Write( NETLIST_DELETEEXTRAFOOTPRINTS_KEY, m_cbDeleteExtraFootprints->GetValue() );
-    m_config->Write( NETLIST_DELETESINGLEPADNETS_KEY, m_cbDeleteSinglePadNets->GetValue() );
-    m_config->Write( NETLIST_FILTER_MESSAGES_KEY, (long) m_messagePanel->GetVisibleSeverities() );
+    auto cfg = m_frame->GetSettings();
+
+    cfg->m_NetlistDialog.update_footprints       = m_cbUpdateFootprints->GetValue();
+    cfg->m_NetlistDialog.delete_extra_footprints = m_cbDeleteExtraFootprints->GetValue();
+    cfg->m_NetlistDialog.delete_single_pad_nets  = m_cbDeleteSinglePadNets->GetValue();
+    cfg->m_NetlistDialog.report_filter           = m_messagePanel->GetVisibleSeverities();
 
     if( m_runDragCommand )
     {
diff --git a/pcbnew/dialogs/dialog_update_pcb.h b/pcbnew/dialogs/dialog_update_pcb.h
index b2e75ca578..b476241649 100644
--- a/pcbnew/dialogs/dialog_update_pcb.h
+++ b/pcbnew/dialogs/dialog_update_pcb.h
@@ -34,7 +34,6 @@ class DIALOG_UPDATE_PCB : public DIALOG_UPDATE_PCB_BASE
 private:
     PCB_EDIT_FRAME* m_frame;
     NETLIST*        m_netlist;
-    wxConfigBase*   m_config;
     bool            m_initialized;
     bool            m_runDragCommand;
     static bool     m_warnForNoNetPads;
diff --git a/pcbnew/dialogs/panel_modedit_settings.cpp b/pcbnew/dialogs/panel_modedit_settings.cpp
index 6693006604..32f1b5ad5a 100644
--- a/pcbnew/dialogs/panel_modedit_settings.cpp
+++ b/pcbnew/dialogs/panel_modedit_settings.cpp
@@ -21,12 +21,13 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <pcbnew.h>
-#include <pcb_edit_frame.h>
 #include <board_design_settings.h>
-#include <widgets/paged_dialog.h>
+#include <fctsys.h>
 #include <footprint_edit_frame.h>
+#include <pcb_edit_frame.h>
+#include <pcbnew.h>
+#include <pcbnew_settings.h>
+#include <widgets/paged_dialog.h>
 
 #include <panel_modedit_settings.h>
 
@@ -46,7 +47,8 @@ bool PANEL_MODEDIT_SETTINGS::TransferDataToWindow()
 
     // Editing options
     m_Segments_45_Only_Ctrl->SetValue( m_frame->Settings().m_Use45DegreeGraphicSegments );
-    m_MagneticPads->SetValue( m_frame->Settings().m_MagneticPads == CAPTURE_ALWAYS );
+    m_MagneticPads->SetValue(
+            m_frame->Settings().m_MagneticPads == MAGNETIC_OPTIONS::CAPTURE_ALWAYS );
 
     return true;
 }
@@ -61,7 +63,8 @@ bool PANEL_MODEDIT_SETTINGS::TransferDataFromWindow()
 
     // Editing options
     m_frame->Settings().m_Use45DegreeGraphicSegments = m_Segments_45_Only_Ctrl->GetValue();
-    m_frame->Settings().m_MagneticPads = m_MagneticPads->GetValue() ? CAPTURE_ALWAYS : NO_EFFECT;
+    m_frame->Settings().m_MagneticPads = m_MagneticPads->GetValue() ?
+            MAGNETIC_OPTIONS::CAPTURE_ALWAYS : MAGNETIC_OPTIONS::NO_EFFECT;
 
     return true;
 }
diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp b/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp
index 01d28bacca..77954b8792 100644
--- a/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp
+++ b/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp
@@ -136,15 +136,14 @@ void PANEL_PCBNEW_ACTION_PLUGINS::OnReloadButtonClick( wxCommandEvent& event )
 
 bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataFromWindow()
 {
-    std::vector< std::pair<wxString, wxString> > pluginSettings;
+    std::vector<wxString> pluginSettings;
 
     pluginSettings.reserve( m_grid->GetNumberRows() );
+
     for( int ii = 0; ii < m_grid->GetNumberRows(); ii++ )
     {
-        pluginSettings.emplace_back(
-                                    m_grid->GetCellValue( ii, COLUMN_PATH ),
-                                    m_grid->GetCellValue( ii, COLUMN_VISIBLE ) == wxT("1") ? wxT( "Visible" ) : wxT( "Hidden" )
-                                );
+        if( m_grid->GetCellValue( ii, COLUMN_VISIBLE ) == wxT( "1" ) )
+            pluginSettings.emplace_back( m_grid->GetCellValue( ii, COLUMN_PATH ) );
     }
 
     m_frame->SetActionPluginSettings( pluginSettings );
diff --git a/pcbnew/dialogs/panel_pcbnew_settings.cpp b/pcbnew/dialogs/panel_pcbnew_settings.cpp
index c5e9c748e3..514503fc6e 100644
--- a/pcbnew/dialogs/panel_pcbnew_settings.cpp
+++ b/pcbnew/dialogs/panel_pcbnew_settings.cpp
@@ -22,15 +22,16 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <pcbnew.h>
-#include <pcb_edit_frame.h>
 #include <board_design_settings.h>
 #include <class_board.h>
+#include <fctsys.h>
 #include <panel_pcbnew_settings.h>
-#include <widgets/paged_dialog.h>
-#include <pcb_view.h>
+#include <pcb_edit_frame.h>
 #include <pcb_painter.h>
+#include <pcb_view.h>
+#include <pcbnew.h>
+#include <pcbnew_settings.h>
+#include <widgets/paged_dialog.h>
 
 PANEL_PCBNEW_SETTINGS::PANEL_PCBNEW_SETTINGS( PCB_EDIT_FRAME* aFrame, PAGED_DIALOG* aParent ) :
         PANEL_PCBNEW_SETTINGS_BASE( aParent->GetTreebook() ),
@@ -41,7 +42,7 @@ PANEL_PCBNEW_SETTINGS::PANEL_PCBNEW_SETTINGS( PCB_EDIT_FRAME* aFrame, PAGED_DIAL
 bool PANEL_PCBNEW_SETTINGS::TransferDataToWindow()
 {
     const PCB_DISPLAY_OPTIONS&  displ_opts = m_Frame->GetDisplayOptions();
-    const PCB_GENERAL_SETTINGS& general_opts = m_Frame->Settings();
+    const PCBNEW_SETTINGS& general_opts = m_Frame->Settings();
 
     /* Set display options */
     m_PolarDisplay->SetSelection( m_Frame->GetShowPolarCoords() ? 1 : 0 );
@@ -56,8 +57,8 @@ bool PANEL_PCBNEW_SETTINGS::TransferDataToWindow()
     m_RotationAngle->SetValue( rotationAngle );
 
     m_Segments_45_Only_Ctrl->SetValue( general_opts.m_Use45DegreeGraphicSegments );
-    m_magneticPadChoice->SetSelection( general_opts.m_MagneticPads );
-    m_magneticTrackChoice->SetSelection( general_opts.m_MagneticTracks );
+    m_magneticPadChoice->SetSelection( static_cast<int>( general_opts.m_MagneticPads ) );
+    m_magneticTrackChoice->SetSelection( static_cast<int>( general_opts.m_MagneticTracks ) );
     m_magneticGraphicsChoice->SetSelection( !general_opts.m_MagneticGraphics );
     m_FlipLeftRight->SetValue( general_opts.m_FlipLeftRight );
 
diff --git a/pcbnew/dialogs/wizard_3DShape_Libs_downloader.cpp b/pcbnew/dialogs/wizard_3DShape_Libs_downloader.cpp
index 61421bdf60..a6c10d02d7 100644
--- a/pcbnew/dialogs/wizard_3DShape_Libs_downloader.cpp
+++ b/pcbnew/dialogs/wizard_3DShape_Libs_downloader.cpp
@@ -36,7 +36,6 @@
 #include <wx/uri.h>
 #include <wx/dir.h>
 #include <wx/progdlg.h>
-#include <wx/config.h>
 
 #include <pgm_base.h>
 #include <project.h>
@@ -44,6 +43,7 @@
 #include <confirm.h>
 #include <3d_viewer/eda_3d_viewer.h>
 #include <bitmaps.h>
+#include <settings/common_settings.h>
 
 #include <../github/github_getliblist.h>
 
@@ -73,14 +73,12 @@ WIZARD_3DSHAPE_LIBS_DOWNLOADER::WIZARD_3DSHAPE_LIBS_DOWNLOADER( wxWindow* aParen
     wxString default_path;
     wxGetEnv( KISYS3DMOD, &default_path );
 
-    wxConfigBase* cfg = Pgm().CommonSettings();
-    wxString tmp;
-    cfg->Read( KICAD_3DLIBS_LAST_DOWNLOAD_DIR, &tmp, default_path );
-    setDownloadDir( tmp );
+    auto cfg = Pgm().GetCommonSettings();
+
+    setDownloadDir( cfg->m_3DLibsDownloadPath.empty() ? default_path : cfg->m_3DLibsDownloadPath );
 
     // Restore the Github 3D shapes libs url
-    wxString githubUrl;
-    cfg->Read( KICAD_3DLIBS_URL_KEY, &githubUrl );
+    wxString githubUrl = cfg->m_3DLibsUrl;
 
     if( githubUrl.IsEmpty() )
         githubUrl = DEFAULT_GITHUB_3DSHAPES_LIBS_URL;
@@ -120,13 +118,10 @@ WIZARD_3DSHAPE_LIBS_DOWNLOADER::WIZARD_3DSHAPE_LIBS_DOWNLOADER( wxWindow* aParen
 
 WIZARD_3DSHAPE_LIBS_DOWNLOADER::~WIZARD_3DSHAPE_LIBS_DOWNLOADER()
 {
-    // Use this if you want to store kicad lib URL in pcbnew/cvpcb section config:
-    // wxConfigBase* cfg = Kiface().KifaceSettings();
+    auto cfg = Pgm().GetCommonSettings();
 
-    // Use this if you want to store kicad lib URL in common section config:
-    wxConfigBase* cfg = Pgm().CommonSettings();
-    cfg->Write( KICAD_3DLIBS_URL_KEY, GetGithubURL() );
-    cfg->Write( KICAD_3DLIBS_LAST_DOWNLOAD_DIR, getDownloadDir() );
+    cfg->m_3DLibsUrl          = GetGithubURL().ToStdString();
+    cfg->m_3DLibsDownloadPath = getDownloadDir().ToStdString();
 }
 
 
diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp
index 6156d2ec83..2d6a6c5eb1 100644
--- a/pcbnew/exporters/export_gencad.cpp
+++ b/pcbnew/exporters/export_gencad.cpp
@@ -29,22 +29,23 @@
  * @brief Export GenCAD 1.4 format.
  */
 
-#include <fctsys.h>
-#include <confirm.h>
-#include <gestfich.h>
-#include <pgm_base.h>
-#include <pcb_edit_frame.h>
-#include <trigo.h>
 #include <build_version.h>
-#include <macros.h>
-#include <pcbnew.h>
-#include <dialogs/dialog_gencad_export_options.h>
 #include <class_board.h>
+#include <class_edge_mod.h>
 #include <class_module.h>
 #include <class_track.h>
-#include <class_edge_mod.h>
+#include <confirm.h>
+#include <dialogs/dialog_gencad_export_options.h>
+#include <fctsys.h>
+#include <gestfich.h>
 #include <hash_eda.h>
-#include <math/util.h>      // for KiROUND
+#include <macros.h>
+#include <math/util.h> // for KiROUND
+#include <pcb_edit_frame.h>
+#include <pcbnew.h>
+#include <pcbnew_settings.h>
+#include <pgm_base.h>
+#include <trigo.h>
 
 static bool CreateHeaderInfoData( FILE* aFile, PCB_EDIT_FRAME* frame );
 static void CreateArtworksSection( FILE* aFile );
diff --git a/pcbnew/exporters/gen_footprints_placefile.cpp b/pcbnew/exporters/gen_footprints_placefile.cpp
index 1abcc41d39..64f8dd1ee2 100644
--- a/pcbnew/exporters/gen_footprints_placefile.cpp
+++ b/pcbnew/exporters/gen_footprints_placefile.cpp
@@ -31,6 +31,7 @@
 #include <kicad_string.h>
 #include <gestfich.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <pgm_base.h>
 #include <bitmaps.h>
 #include <build_version.h>
@@ -48,12 +49,6 @@
 #include "gerber_placefile_writer.h"
 
 
-#define PLACEFILE_UNITS_KEY  wxT( "PlaceFileUnits" )
-#define PLACEFILE_OPT_KEY    wxT( "PlaceFileOpts" )
-#define PLACEFILE_FORMAT_KEY wxT( "PlaceFileFormat" )
-#define PLACEFILE_INCLUDE_BRD_EDGE_KEY wxT( "PlaceFileIncludeBrdEdge" )
-
-
 /**
  * The dialog to create footprint position files and choose options (one or 2 files, units
  * and force all SMD footprints in list)
@@ -84,7 +79,6 @@ public:
 private:
     PCB_EDIT_FRAME* m_parent;
     PCB_PLOT_PARAMS m_plotOpts;
-    wxConfigBase* m_config;
     REPORTER* m_reporter;
 
     static int m_unitsOpt;
@@ -159,11 +153,12 @@ void DIALOG_GEN_FOOTPRINT_POSITION::initDialog()
 {
     m_browseButton->SetBitmap( KiBitmap( folder_xpm ) );
 
-    m_config = Kiface().KifaceSettings();
-    m_config->Read( PLACEFILE_UNITS_KEY, &m_unitsOpt, 1 );
-    m_config->Read( PLACEFILE_OPT_KEY, &m_fileOpt, 0 );
-    m_config->Read( PLACEFILE_FORMAT_KEY, &m_fileFormat, 0 );
-    m_config->Read( PLACEFILE_INCLUDE_BRD_EDGE_KEY, &m_includeBoardEdge, false );
+    auto cfg = m_parent->GetSettings();
+
+    m_units            = static_cast<EDA_UNITS>( cfg->m_PlaceFile.units );
+    m_fileOpt          = cfg->m_PlaceFile.file_options;
+    m_fileFormat       = cfg->m_PlaceFile.file_format;
+    m_includeBoardEdge = cfg->m_PlaceFile.include_board_edge;
 
     // Output directory
     m_outputDirectoryName->SetValue( m_plotOpts.GetOutputDirectory() );
@@ -216,10 +211,12 @@ void DIALOG_GEN_FOOTPRINT_POSITION::OnGenerate( wxCommandEvent& event )
     m_fileFormat = m_rbFormat->GetSelection();
     m_includeBoardEdge = m_cbIncludeBoardEdge->GetValue();
 
-    m_config->Write( PLACEFILE_UNITS_KEY, m_unitsOpt );
-    m_config->Write( PLACEFILE_OPT_KEY, m_fileOpt );
-    m_config->Write( PLACEFILE_FORMAT_KEY, m_fileFormat );
-    m_config->Write( PLACEFILE_INCLUDE_BRD_EDGE_KEY, m_includeBoardEdge );
+    auto cfg = m_parent->GetSettings();
+
+    cfg->m_PlaceFile.units              = static_cast<int>( m_units );
+    cfg->m_PlaceFile.file_options       = m_fileOpt;
+    cfg->m_PlaceFile.file_format        = m_fileFormat;
+    cfg->m_PlaceFile.include_board_edge = m_includeBoardEdge;
 
     // Set output directory and replace backslashes with forward ones
     // (Keep unix convention in cfg files)
diff --git a/pcbnew/footprint_edit_frame.cpp b/pcbnew/footprint_edit_frame.cpp
index e9b84e60f0..bc371e62d3 100644
--- a/pcbnew/footprint_edit_frame.cpp
+++ b/pcbnew/footprint_edit_frame.cpp
@@ -20,51 +20,54 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <fctsys.h>
-#include <kiface_i.h>
-#include <kiway.h>
-#include <project.h>
-#include <kicad_plugin.h>
-#include <pcb_draw_panel_gal.h>
-#include <confirm.h>
-#include <pcb_edit_frame.h>
+#include "tools/drawing_tool.h"
+#include "tools/edit_tool.h"
+#include "tools/footprint_editor_tools.h"
+#include "tools/pad_tool.h"
+#include "tools/pcb_actions.h"
+#include "tools/pcbnew_control.h"
+#include "tools/pcbnew_picker_tool.h"
+#include "tools/placement_tool.h"
+#include "tools/point_editor.h"
+#include "tools/selection_tool.h"
 #include <3d_viewer/eda_3d_viewer.h>
-#include <fp_lib_table.h>
 #include <bitmaps.h>
 #include <class_board.h>
 #include <class_module.h>
+#include <confirm.h>
+#include <dialogs/panel_modedit_defaults.h>
+#include <dialogs/panel_modedit_display_options.h>
+#include <dialogs/panel_modedit_settings.h>
+#include <fctsys.h>
+#include <footprint_edit_frame.h>
+#include <footprint_editor_settings.h>
+#include <footprint_info_impl.h>
+#include <footprint_tree_pane.h>
+#include <footprint_viewer_frame.h>
+#include <fp_lib_table.h>
+#include <kicad_plugin.h>
+#include <kiface_i.h>
+#include <kiway.h>
+#include <panel_hotkeys_editor.h>
+#include <pcb_draw_panel_gal.h>
+#include <pcb_edit_frame.h>
+#include <pcb_layer_widget.h>
 #include <pcbnew.h>
 #include <pcbnew_id.h>
-#include <footprint_edit_frame.h>
-#include <footprint_viewer_frame.h>
-#include <wildcards_and_files_ext.h>
-#include <pcb_layer_widget.h>
-#include <tool/tool_manager.h>
+#include <pgm_base.h>
+#include <project.h>
+#include <settings/settings_manager.h>
+#include <tool/action_toolbar.h>
 #include <tool/common_control.h>
 #include <tool/common_tools.h>
 #include <tool/tool_dispatcher.h>
-#include <tool/action_toolbar.h>
+#include <tool/tool_manager.h>
 #include <tool/zoom_tool.h>
-#include <footprint_tree_pane.h>
-#include <widgets/lib_tree.h>
-#include <footprint_info_impl.h>
-#include <widgets/paged_dialog.h>
-#include <dialogs/panel_modedit_settings.h>
-#include <dialogs/panel_modedit_defaults.h>
-#include <dialogs/panel_modedit_display_options.h>
-#include <panel_hotkeys_editor.h>
 #include <tools/position_relative_tool.h>
+#include <widgets/lib_tree.h>
+#include <widgets/paged_dialog.h>
 #include <widgets/progress_reporter.h>
-#include "tools/selection_tool.h"
-#include "tools/edit_tool.h"
-#include "tools/drawing_tool.h"
-#include "tools/point_editor.h"
-#include "tools/pcbnew_control.h"
-#include "tools/footprint_editor_tools.h"
-#include "tools/placement_tool.h"
-#include "tools/pcbnew_picker_tool.h"
-#include "tools/pad_tool.h"
-#include "tools/pcb_actions.h"
+#include <wildcards_and_files_ext.h>
 
 
 BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME )
@@ -97,7 +100,6 @@ BEGIN_EVENT_TABLE( FOOTPRINT_EDIT_FRAME, PCB_BASE_FRAME )
 
 END_EVENT_TABLE()
 
-static const wxChar defaultLibWidthEntry[] =        wxT( "ModeditLibWidth" );
 
 FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent,
                                             EDA_DRAW_PANEL_GAL::GAL_TYPE aBackend ) :
@@ -110,6 +112,7 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent,
     m_canvasType = aBackend;
     m_AboutTitle = "ModEdit";
     m_selLayerBox = nullptr;
+    m_settings = nullptr;
 
     // Give an icon
     wxIcon icon;
@@ -162,7 +165,8 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent,
 
     // LoadSettings() *after* creating m_LayersManager, because LoadSettings()
     // initialize parameters in m_LayersManager
-    LoadSettings( config() );
+    // NOTE: KifaceSettings() will return PCBNEW_SETTINGS if we started from pcbnew
+    LoadSettings( GetSettings() );
     GetGalDisplayOptions().m_axesEnabled = true;
 
     SetScreen( new PCB_SCREEN( GetPageSettings().GetSizeIU() ) );
@@ -418,16 +422,32 @@ void FOOTPRINT_EDIT_FRAME::SetPlotSettings( const PCB_PLOT_PARAMS& aSettings )
 }
 
 
-void FOOTPRINT_EDIT_FRAME::LoadSettings( wxConfigBase* aCfg )
+FOOTPRINT_EDITOR_SETTINGS* FOOTPRINT_EDIT_FRAME::GetSettings()
 {
-    PCB_BASE_FRAME::LoadSettings( aCfg );
-    wxConfigLoadSetups( aCfg, GetConfigurationSettings() );
+    if( !m_settings )
+        m_settings = Pgm().GetSettingsManager().GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>();
 
-    m_configSettings.Load( aCfg );  // mainly, load the color config
+    return m_settings;
+}
+
+
+void FOOTPRINT_EDIT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
+{
+    // aCfg will be the PCBNEW_SETTINGS
+    auto cfg = GetSettings();
+
+    EDA_BASE_FRAME::LoadSettings( cfg );
+
+    // TODO(JE) remove once color themes exist
+    COLOR_SETTINGS* cs = ColorSettings();
+    cs->SetColorContext( COLOR_CONTEXT::FOOTPRINT );
+    cs->Load();
 
     // Ensure some params are valid
     BOARD_DESIGN_SETTINGS& settings = GetDesignSettings();
 
+    settings = cfg->m_DesignSettings;
+
     // Usually, graphic items are drawn on F_SilkS or F_Fab layer
     // Force these layers if not default
     if( ( settings.m_RefDefaultlayer != F_SilkS ) && ( settings.m_RefDefaultlayer != F_Fab ) )
@@ -436,18 +456,27 @@ void FOOTPRINT_EDIT_FRAME::LoadSettings( wxConfigBase* aCfg )
     if( ( settings.m_ValueDefaultlayer != F_SilkS ) && ( settings.m_ValueDefaultlayer != F_Fab ) )
         settings.m_ValueDefaultlayer = F_Fab;
 
-    aCfg->Read( defaultLibWidthEntry, &m_defaultLibWidth, 250 );
+    m_DisplayOptions = cfg->m_Display;
+    m_defaultLibWidth = cfg->m_LibWidth;
 }
 
 
-void FOOTPRINT_EDIT_FRAME::SaveSettings( wxConfigBase* aCfg )
+void FOOTPRINT_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
-    m_configSettings.Save( aCfg );
+    // aCfg will be the PCBNEW_SETTINGS
+    auto cfg = GetSettings();
 
-    PCB_BASE_FRAME::SaveSettings( aCfg );
-    wxConfigSaveSetups( aCfg, GetConfigurationSettings() );
+    EDA_BASE_FRAME::SaveSettings( cfg );
 
-    aCfg->Write( defaultLibWidthEntry, m_treePane->GetSize().x );
+    cfg->m_DesignSettings = GetDesignSettings();
+    cfg->m_Display = m_DisplayOptions;
+    cfg->m_LibWidth = m_treePane->GetSize().x;
+
+    // TODO(JE) remove once color themes exist
+    // Ensure footprint editor color settings get flushed to disk before context is changed
+    COLOR_SETTINGS* cs = ColorSettings();
+    cs->SetColorContext( COLOR_CONTEXT::FOOTPRINT );
+    Pgm().GetSettingsManager().SaveColorSettings( cs, "fpedit" );
 }
 
 
@@ -672,7 +701,7 @@ void FOOTPRINT_EDIT_FRAME::UpdateUserInterface()
 
 void FOOTPRINT_EDIT_FRAME::updateView()
 {
-    GetCanvas()->UseColorScheme( &Settings().Colors() );
+    GetCanvas()->UpdateColors();
     GetCanvas()->DisplayBoard( GetBoard() );
     m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
     m_toolManager->RunAction( ACTIONS::zoomFitScreen, true );
diff --git a/pcbnew/footprint_edit_frame.h b/pcbnew/footprint_edit_frame.h
index a6ce6369a8..40f3ccafaa 100644
--- a/pcbnew/footprint_edit_frame.h
+++ b/pcbnew/footprint_edit_frame.h
@@ -31,6 +31,7 @@ class FP_LIB_TABLE;
 class EDGE_MODULE;
 class FOOTPRINT_TREE_PANE;
 class LIB_MANAGER;
+class FOOTPRINT_EDITOR_SETTINGS;
 
 namespace PCB { struct IFACE; }     // A KIFACE_I coded in pcbnew.c
 
@@ -70,30 +71,19 @@ public:
 
     bool IsCurrentFPFromBoard() const;
 
+    FOOTPRINT_EDITOR_SETTINGS* GetSettings();
+
     BOARD_DESIGN_SETTINGS& GetDesignSettings() const override;
     void SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings ) override;
 
     const PCB_PLOT_PARAMS& GetPlotSettings() const override;
     void SetPlotSettings( const PCB_PLOT_PARAMS& aSettings ) override;
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     const BOX2I GetDocumentExtents() const override;
 
-    /**
-     * Return the footprint editor settings list.
-     *
-     * Currently, only the settings that are needed at start
-     * up by the main window are defined here.  There are other locally used
-     * settings that are scattered throughout the Pcbnew source code.  If you need
-     * to define a configuration setting that needs to be loaded at run time,
-     * this is the place to define it.
-     *
-     * @return - Reference to the list of applications settings.
-     */
-    std::vector<PARAM_CFG*>& GetConfigurationSettings();
-
     void OnCloseWindow( wxCloseEvent& Event ) override;
     void CloseModuleEditor( wxCommandEvent& Event );
     void OnExitKiCad( wxCommandEvent& aEvent );
@@ -356,7 +346,8 @@ protected:
     FOOTPRINT_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent, EDA_DRAW_PANEL_GAL::GAL_TYPE aBackend );
 
     PCB_LAYER_BOX_SELECTOR* m_selLayerBox;  // a combo box to display and select active layer
-    std::vector<PARAM_CFG*> m_configParams; // List of footprint editor configuration parameters.
+
+    FOOTPRINT_EDITOR_SETTINGS* m_settings;
 
     /**
      * Make sure the footprint info list is loaded (with a progress dialog) and then initialize
diff --git a/pcbnew/footprint_editor_options.cpp b/pcbnew/footprint_editor_options.cpp
deleted file mode 100644
index f55bc18126..0000000000
--- a/pcbnew/footprint_editor_options.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * This program source code file is part of KiCad, a free EDA CAD application.
- *
- * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
- * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
- * Copyright (C) 2015 Wayne Stambaugh <stambaughw@verizon.net>
- * Copyright (C) 1992-2018 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 2
- * 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, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-#include <fctsys.h>
-#include <pcbnew.h>
-#include <footprint_edit_frame.h>
-#include <board_design_settings.h>
-#include <layers_id_colors_and_visibility.h>
-
-
-std::vector<PARAM_CFG*>& FOOTPRINT_EDIT_FRAME::GetConfigurationSettings()
-{
-    auto& displ_opts = m_DisplayOptions;
-    BOARD_DESIGN_SETTINGS& settings = GetDesignSettings();
-
-    // Update everything
-    m_configParams.clear();   // boost::ptr_vector destroys the pointers inside
-
-    // Display options:
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorDisplayPolarCoords" ),
-                                                  &m_PolarCoords, false ) );
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorPadDisplayMode" ),
-                                                  &displ_opts.m_DisplayPadFill, true ) );
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorGraphicLinesDisplayMode" ),
-                                                  &displ_opts.m_DisplayModEdgeFill, FILLED ) );
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorTextsDisplayMode" ),
-                                                  &displ_opts.m_DisplayModTextFill, FILLED ) );
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorTextsDisplayMode" ),
-                                                  &displ_opts.m_DisplayModTextFill, FILLED ) );
-    m_configParams.push_back( new PARAM_CFG_WXSTRING( true, wxT( "FpEditorTextsRefDefaultText" ),
-                                                      &settings.m_RefDefaultText, wxT( "REF**" ) ) );
-
-    // design settings
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorSilkLineWidth" ),
-            &settings.m_LineThickness[ LAYER_CLASS_SILK ],
-            Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 100.0 ),
-            nullptr, 1/IU_PER_MM, wxT( "FpEditorGrlineWidth" ) ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorSilkTextSizeH" ),
-            &settings.m_TextSize[ LAYER_CLASS_SILK ].x,
-            Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
-            nullptr, 1/IU_PER_MM, wxT( "FpEditorTextsDefaultSizeH" ) ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorSilkTextSizeV" ),
-            &settings.m_TextSize[ LAYER_CLASS_SILK ].y,
-            Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
-            nullptr, 1/IU_PER_MM, wxT( "FpEditorTextsDefaultSizeV" ) ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorSilkTextThickness" ),
-            &settings.m_TextThickness[ LAYER_CLASS_SILK ],
-            Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH,
-            nullptr, 1/IU_PER_MM, wxT( "FpEditorTextsDefaultThickness" ) ) );
-
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorSilkTextItalic" ),
-            &settings.m_TextItalic[ LAYER_CLASS_SILK ] ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorCopperLineWidth" ),
-            &settings.m_LineThickness[ LAYER_CLASS_COPPER ],
-            Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorCopperTextSizeV" ),
-            &settings.m_TextSize[ LAYER_CLASS_COPPER ].y,
-            Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE  ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorCopperTextSizeH" ),
-            &settings.m_TextSize[ LAYER_CLASS_COPPER ].x,
-            Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE  ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorCopperTextThickness" ),
-            &settings.m_TextThickness[ LAYER_CLASS_COPPER ],
-            Millimeter2iu( DEFAULT_COPPER_TEXT_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorCopperTextItalic" ),
-            &settings.m_TextItalic[ LAYER_CLASS_COPPER ] ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorEdgeCutLineWidth" ),
-            &settings.m_LineThickness[ LAYER_CLASS_EDGES ],
-            Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorCourtyardLineWidth" ),
-            &settings.m_LineThickness[ LAYER_CLASS_COURTYARD ],
-            Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorOthersLineWidth" ),
-            &settings.m_LineThickness[ LAYER_CLASS_OTHERS ],
-            Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorOthersTextSizeV" ),
-            &settings.m_TextSize[ LAYER_CLASS_OTHERS ].x,
-            Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorOthersTextSizeH" ),
-            &settings.m_TextSize[ LAYER_CLASS_OTHERS ].y,
-            Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT_WITH_SCALE( true, wxT( "FpEditorOthersTextSizeThickness" ),
-            &settings.m_TextThickness[ LAYER_CLASS_OTHERS ],
-            Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH,
-            nullptr, MM_PER_IU ) );
-
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorOthersTextItalic" ),
-            &settings.m_TextItalic[ LAYER_CLASS_OTHERS ] ) );
-
-    m_configParams.push_back( new PARAM_CFG_WXSTRING( true, wxT( "FpEditorRefDefaultText" ),
-            &settings.m_RefDefaultText, wxT( "REF**" ) ) );
-
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorRefDefaultVisibility" ),
-            &settings.m_RefDefaultVisibility, true ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT( true, wxT( "FpEditorRefDefaultLayer" ),
-            &settings.m_RefDefaultlayer,
-            int( F_SilkS ), int( F_SilkS ), int( F_Fab ) ) );
-
-    m_configParams.push_back( new PARAM_CFG_WXSTRING( true, wxT( "FpEditorValueDefaultText" ),
-            &settings.m_ValueDefaultText, wxT( "" ) ) );
-
-    m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "FpEditorValueDefaultVisibility" ),
-            &settings.m_ValueDefaultVisibility, true ) );
-
-    m_configParams.push_back( new PARAM_CFG_INT( true, wxT( "FpEditorValueDefaultLayer" ),
-            &settings.m_ValueDefaultlayer,
-            int( F_Fab ), int( F_SilkS ), int( F_Fab ) ) );
-
-    return m_configParams;
-}
diff --git a/pcbnew/footprint_editor_settings.cpp b/pcbnew/footprint_editor_settings.cpp
new file mode 100644
index 0000000000..b148768dcb
--- /dev/null
+++ b/pcbnew/footprint_editor_settings.cpp
@@ -0,0 +1,266 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 <common.h>
+#include <footprint_editor_settings.h>
+#include <layers_id_colors_and_visibility.h>
+#include <pgm_base.h>
+#include <settings/common_settings.h>
+#include <settings/parameters.h>
+#include <settings/settings_manager.h>
+#include <wx/config.h>
+
+
+///! Update the schema version whenever a migration is required
+const int fpEditSchemaVersion = 0;
+
+
+FOOTPRINT_EDITOR_SETTINGS::FOOTPRINT_EDITOR_SETTINGS() :
+        APP_SETTINGS_BASE( "fpedit", fpEditSchemaVersion ), m_DesignSettings(), m_MagneticPads(),
+        m_Display(), m_UserGrid(), m_PolarCoords( false ), m_Use45DegreeGraphicSegments( true ),
+        m_LibWidth( 250 ), m_LastImportExportPath(), m_FootprintTextShownColumns()
+{
+    m_params.emplace_back( new PARAM<int>( "window.lib_width", &m_LibWidth, 250 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "system.last_import_export_path",
+            &m_LastImportExportPath, "" ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "window.footprint_text_shown_columns",
+            &m_FootprintTextShownColumns, "0 1 2 3 4 5 6" ) );
+
+    m_params.emplace_back( new PARAM<int>( "editing.magnetic_pads",
+            reinterpret_cast<int*>( &m_MagneticPads ),
+            static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ) ) );
+
+    m_params.emplace_back( new PARAM<bool>( "editing.polar_coords", &m_PolarCoords, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "editing.use_45_degree_graphic_segments",
+            &m_Use45DegreeGraphicSegments, false ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "pcb_display.footprint_text", &m_Display.m_DisplayModTextFill, true ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "pcb_display.graphic_items_fill", &m_Display.m_DisplayDrawItemsFill, true ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "pcb_display.pad_fill", &m_Display.m_DisplayPadFill, true ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_line_width",
+            &m_DesignSettings.m_LineThickness[ LAYER_CLASS_SILK ],
+            Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 100.0 ),
+            MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_h",
+            &m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].x,
+            Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_size_v",
+            &m_DesignSettings.m_TextSize[ LAYER_CLASS_SILK ].y,
+            Millimeter2iu( DEFAULT_SILK_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.silk_text_thickness",
+            &m_DesignSettings.m_TextThickness[ LAYER_CLASS_SILK ],
+            Millimeter2iu( DEFAULT_SILK_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM<bool>( "design_settings.silk_text_italic",
+            &m_DesignSettings.m_TextItalic[ LAYER_CLASS_SILK ], false ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_line_width",
+            &m_DesignSettings.m_LineThickness[ LAYER_CLASS_COPPER ],
+            Millimeter2iu( DEFAULT_COPPER_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+            MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_h",
+            &m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].x,
+            Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
+            MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_size_v",
+            &m_DesignSettings.m_TextSize[ LAYER_CLASS_COPPER ].y,
+            Millimeter2iu( DEFAULT_COPPER_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE,
+            MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.copper_text_thickness",
+            &m_DesignSettings.m_TextThickness[ LAYER_CLASS_COPPER ],
+            Millimeter2iu( DEFAULT_COPPER_TEXT_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+            MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM<bool>( "design_settings.copper_text_italic",
+            &m_DesignSettings.m_TextItalic[ LAYER_CLASS_COPPER ], false ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.edge_line_width",
+            &m_DesignSettings.m_LineThickness[ LAYER_CLASS_EDGES ],
+            Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+            MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.courtyard_line_width",
+            &m_DesignSettings.m_LineThickness[ LAYER_CLASS_COURTYARD ],
+            Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+            MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_line_width",
+           &m_DesignSettings.m_LineThickness[ LAYER_CLASS_OTHERS ],
+           Millimeter2iu( DEFAULT_SILK_LINE_WIDTH ), Millimeter2iu( 0.01 ), Millimeter2iu( 5.0 ),
+           MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_h",
+           &m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].x,
+           Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_size_v",
+           &m_DesignSettings.m_TextSize[ LAYER_CLASS_OTHERS ].y,
+           Millimeter2iu( DEFAULT_TEXT_SIZE ), TEXTS_MIN_SIZE, TEXTS_MAX_SIZE, MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM_SCALED<int>( "design_settings.others_text_thickness",
+           &m_DesignSettings.m_TextThickness[ LAYER_CLASS_OTHERS ],
+           Millimeter2iu( DEFAULT_TEXT_WIDTH ), 1, TEXTS_MAX_WIDTH, MM_PER_IU ) );
+
+    m_params.emplace_back( new PARAM<bool>( "design_settings.others_text_italic",
+            &m_DesignSettings.m_TextItalic[ LAYER_CLASS_OTHERS ], false ) );
+
+    m_params.emplace_back( new PARAM<int>( "design_settings.default_ref_layer",
+            &m_DesignSettings.m_RefDefaultlayer, F_SilkS, F_SilkS, F_Fab ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "design_settings.default_ref_text",
+            &m_DesignSettings.m_RefDefaultText, "REF**" ) );
+
+    m_params.emplace_back( new PARAM<bool>( "design_settings.default_ref_visibility",
+            &m_DesignSettings.m_RefDefaultVisibility, true ) );
+
+    m_params.emplace_back( new PARAM<int>( "design_settings.default_value_layer",
+            &m_DesignSettings.m_ValueDefaultlayer, F_SilkS, F_SilkS, F_Fab ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "design_settings.default_value_text",
+            &m_DesignSettings.m_ValueDefaultText, "" ) );
+
+    m_params.emplace_back( new PARAM<bool>( "design_settings.default_value_visibility",
+            &m_DesignSettings.m_ValueDefaultVisibility, true ) );
+}
+
+
+bool FOOTPRINT_EDITOR_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    ret &= fromLegacy<int>(  aCfg, "ModeditLibWidth",   "window.lib_width" );
+    ret &= fromLegacyString( aCfg, "import_last_path",  "system.last_import_export_path" );
+    ret &= fromLegacyString(
+            aCfg, "LibFootprintTextShownColumns", "window.footprint_text_shown_columns" );
+
+    ret &= fromLegacy<int>(  aCfg, "FpEditorMagneticPads",          "editing.magnetic_pads" );
+    ret &= fromLegacy<bool>( aCfg, "FpEditorDisplayPolarCoords",    "editing.polar_coords" );
+    ret &= fromLegacy<int>(  aCfg,
+            "FpEditorUse45DegreeGraphicSegments", "editing.use_45_degree_graphic_segments" );
+
+    ret &= fromLegacy<bool>(  aCfg,
+            "FpEditorGraphicLinesDisplayMode", "pcb_display.graphic_items_fill" );
+    ret &= fromLegacy<bool>(  aCfg, "FpEditorPadDisplayMode",   "pcb_display.pad_fill" );
+    ret &= fromLegacy<bool>(  aCfg, "FpEditorTextsDisplayMode", "pcb_display.footprint_text" );
+
+    ret &= fromLegacy<double>( aCfg, "FpEditorSilkLineWidth", "design_settings.silk_line_width" );
+    ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeH", "design_settings.silk_text_size_h" );
+    ret &= fromLegacy<double>( aCfg, "FpEditorSilkTextSizeV", "design_settings.silk_text_size_v" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorSilkTextThickness", "design_settings.silk_text_thickness" );
+    ret &= fromLegacy<bool>(   aCfg, "FpEditorSilkTextItalic", "design_settings.silk_text_italic" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorCopperLineWidth", "design_settings.copper_line_width" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorCopperTextSizeH", "design_settings.copper_text_size_h" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorCopperTextSizeV", "design_settings.copper_text_size_v" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorCopperTextThickness", "design_settings.copper_text_thickness" );
+    ret &= fromLegacy<bool>(   aCfg,
+            "FpEditorCopperTextItalic", "design_settings.copper_text_italic" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorEdgeCutLineWidth", "design_settings.edge_line_width" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorCourtyardLineWidth", "design_settings.courtyard_line_width" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorOthersLineWidth", "design_settings.others_line_width" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorOthersTextSizeH", "design_settings.others_text_size_h" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorOthersTextSizeV", "design_settings.others_text_size_v" );
+    ret &= fromLegacy<double>( aCfg,
+            "FpEditorOthersTextSizeThickness", "design_settings.others_text_thickness" );
+    ret &= fromLegacy<bool>( aCfg,
+            "FpEditorOthersTextItalic", "design_settings.others_text_italic" );
+    ret &= fromLegacy<int>(  aCfg, "FpEditorRefDefaultLayer", "design_settings.default_ref_layer" );
+    ret &= fromLegacyString( aCfg, "FpEditorRefDefaultText", "design_settings.default_ref_text" );
+    ret &= fromLegacy<bool>( aCfg,
+            "FpEditorRefDefaultVisibility", "design_settings.default_ref_visibility" );
+    ret &= fromLegacy<int>( aCfg,
+            "FpEditorValueDefaultLayer", "design_settings.default_value_layer" );
+    ret &= fromLegacyString( aCfg,
+            "FpEditorValueDefaultText", "design_settings.default_value_text" );
+    ret &= fromLegacy<bool>( aCfg,
+            "FpEditorValueDefaultVisibility", "design_settings.default_value_visibility" );
+
+    const std::string f = "ModEdit";
+
+    // Migrate color settings that were stored in the pcbnew config file
+
+    SETTINGS_MANAGER& manager = Pgm().GetSettingsManager();
+    COLOR_SETTINGS* cs = manager.GetColorSettings();
+
+    // Flush here just in case we somehow have dirty pcbnew colors
+    manager.Save( cs );
+
+    cs->SetColorContext( COLOR_CONTEXT::FOOTPRINT );
+
+    auto migrateLegacyColor = [&] ( const std::string& aKey, int aLayerId ) {
+        wxString str;
+
+        if( aCfg->Read( aKey, &str ) )
+            cs->SetColor( aLayerId, COLOR4D( str ) );
+    };
+
+    for( int i = 0; i < PCB_LAYER_ID_COUNT; ++i )
+    {
+        wxString layer = LSET::Name( PCB_LAYER_ID( i ) );
+        migrateLegacyColor( f + "Color4DPCBLayer_" + layer.ToStdString(), PCB_LAYER_ID( i ) );
+    }
+
+    migrateLegacyColor( f + "Color4DAnchorEx",           LAYER_ANCHOR );
+    migrateLegacyColor( f + "Color4DAuxItems",           LAYER_AUX_ITEMS );
+    migrateLegacyColor( f + "Color4DGrid",               LAYER_GRID );
+    migrateLegacyColor( f + "Color4DNoNetPadMarker",     LAYER_NO_CONNECTS );
+    migrateLegacyColor( f + "Color4DNonPlatedEx",        LAYER_NON_PLATEDHOLES );
+    migrateLegacyColor( f + "Color4DPadBackEx",          LAYER_PAD_BK );
+    migrateLegacyColor( f + "Color4DPadFrontEx",         LAYER_PAD_FR );
+    migrateLegacyColor( f + "Color4DPadThruHoleEx",      LAYER_PADS_TH );
+    migrateLegacyColor( f + "Color4DPCBBackground",      LAYER_PCB_BACKGROUND );
+    migrateLegacyColor( f + "Color4DPCBCursor",          LAYER_CURSOR );
+    migrateLegacyColor( f + "Color4DRatsEx",             LAYER_RATSNEST );
+    migrateLegacyColor( f + "Color4DTxtBackEx",          LAYER_MOD_TEXT_BK );
+    migrateLegacyColor( f + "Color4DTxtFrontEx",         LAYER_MOD_TEXT_FR );
+    migrateLegacyColor( f + "Color4DTxtInvisEx",         LAYER_MOD_TEXT_INVISIBLE );
+    migrateLegacyColor( f + "Color4DViaBBlindEx",        LAYER_VIA_BBLIND );
+    migrateLegacyColor( f + "Color4DViaMicroEx",         LAYER_VIA_MICROVIA );
+    migrateLegacyColor( f + "Color4DViaThruEx",          LAYER_VIA_THROUGH );
+    migrateLegacyColor( f + "Color4DWorksheet",          LAYER_WORKSHEET );
+
+    manager.Save( cs );
+
+    return ret;
+}
diff --git a/pcbnew/footprint_editor_settings.h b/pcbnew/footprint_editor_settings.h
new file mode 100644
index 0000000000..9b9d3cc6ad
--- /dev/null
+++ b/pcbnew/footprint_editor_settings.h
@@ -0,0 +1,70 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 FOOTPRINT_EDITOR_SETTINGS_H_
+#define FOOTPRINT_EDITOR_SETTINGS_H_
+
+#include <board_design_settings.h>
+#include <settings/app_settings.h>
+#include <pcbnew_settings.h>
+
+
+class FOOTPRINT_EDITOR_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+    struct USER_GRID
+    {
+        double size_x;
+        double size_y;
+        int units;
+    };
+
+    FOOTPRINT_EDITOR_SETTINGS();
+
+    virtual ~FOOTPRINT_EDITOR_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    BOARD_DESIGN_SETTINGS m_DesignSettings;
+
+    MAGNETIC_OPTIONS m_MagneticPads;
+
+    PCB_DISPLAY_OPTIONS m_Display;
+
+    USER_GRID m_UserGrid;
+
+    bool m_PolarCoords;
+
+    bool m_Use45DegreeGraphicSegments;   // True to constraint graphic lines to horizontal,
+    // vertical and 45ยบ
+
+    int m_LibWidth;
+
+    wxString m_LastImportExportPath;
+
+    wxString m_FootprintTextShownColumns;
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "ModEditFrame"; }
+};
+
+
+#endif
diff --git a/pcbnew/footprint_editor_utils.cpp b/pcbnew/footprint_editor_utils.cpp
index 9b04021d3f..f5473e80f8 100644
--- a/pcbnew/footprint_editor_utils.cpp
+++ b/pcbnew/footprint_editor_utils.cpp
@@ -21,45 +21,47 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
+#include <3d_viewer/eda_3d_viewer.h>
+#include <board_commit.h>
+#include <class_board.h>
+#include <class_edge_mod.h>
+#include <class_module.h>
+#include <collectors.h>
+#include <config_params.h>
+#include <confirm.h>
+#include <dialog_create_array.h>
+#include <dialog_edit_footprint_for_fp_editor.h>
+#include <dialog_move_exact.h>
 #include <fctsys.h>
+#include <footprint_edit_frame.h>
+#include <footprint_tree_pane.h>
+#include <footprint_viewer_frame.h>
+#include <footprint_wizard_frame.h>
+#include <fp_lib_table.h>
+#include <functional>
+#include <gestfich.h>
+#include <invoke_pcb_dialog.h>
 #include <kiface_i.h>
 #include <kiway.h>
 #include <kiway_express.h>
-#include <pcb_draw_panel_gal.h>
-#include <confirm.h>
-#include <gestfich.h>
-#include <pgm_base.h>
-#include <trigo.h>
-#include <3d_viewer/eda_3d_viewer.h>
 #include <macros.h>
-#include <invoke_pcb_dialog.h>
-#include <pcb_layer_widget.h>
-#include <board_commit.h>
-#include <view/view.h>
-#include <class_board.h>
-#include <class_module.h>
-#include <class_edge_mod.h>
+#include <menus_helpers.h>
+#include <pcb_draw_panel_gal.h>
 #include <pcb_layer_box_selector.h>
-#include <ratsnest_data.h>
+#include <pcb_layer_widget.h>
 #include <pcbnew.h>
 #include <pcbnew_id.h>
-#include <footprint_edit_frame.h>
-#include <footprint_viewer_frame.h>
-#include <footprint_tree_pane.h>
-#include <fp_lib_table.h>
-#include <widgets/lib_tree.h>
-#include <collectors.h>
+#include <pcbnew_settings.h>
+#include <pgm_base.h>
+#include <ratsnest_data.h>
+#include <settings/color_settings.h>
 #include <tool/tool_manager.h>
 #include <tools/pcb_actions.h>
-#include <dialog_edit_footprint_for_fp_editor.h>
-#include <dialog_move_exact.h>
-#include <dialog_create_array.h>
+#include <trigo.h>
+#include <view/view.h>
+#include <widgets/lib_tree.h>
 #include <wildcards_and_files_ext.h>
-#include <menus_helpers.h>
-#include <footprint_wizard_frame.h>
-#include <config_params.h>
 
-#include <functional>
 using namespace std::placeholders;
 
 
@@ -428,7 +430,7 @@ void FOOTPRINT_EDIT_FRAME::OnEditItemRequest( BOARD_ITEM* aItem )
 
 COLOR4D FOOTPRINT_EDIT_FRAME::GetGridColor()
 {
-    return Settings().Colors().GetItemColor( LAYER_GRID );
+    return ColorSettings()->GetColor( LAYER_GRID );
 }
 
 
diff --git a/pcbnew/footprint_libraries_utils.cpp b/pcbnew/footprint_libraries_utils.cpp
index 863a7cfa0b..35bbc6a096 100644
--- a/pcbnew/footprint_libraries_utils.cpp
+++ b/pcbnew/footprint_libraries_utils.cpp
@@ -44,6 +44,8 @@
 #include <kicad_plugin.h>
 #include <legacy_plugin.h>
 #include <env_paths.h>
+#include <settings/settings_manager.h>
+#include <footprint_editor_settings.h>
 #include "footprint_viewer_frame.h"
 
 
@@ -79,9 +81,6 @@ static const wxString INFO_LEGACY_LIB_WARN_DELETE(
             "before deleting a footprint" ) );
 
 
-#define EXPORT_IMPORT_LASTPATH_KEY wxT( "import_last_path" )
-
-
 /**
  * Prompt the user for a module file to open.
  * @param aParent - parent window for the dialog
@@ -243,11 +242,11 @@ MODULE* try_load_footprint( const wxFileName& aFileName, IO_MGR::PCB_FILE_T aFil
 
 MODULE* FOOTPRINT_EDIT_FRAME::Import_Module( const wxString& aName )
 {
-    wxString        lastOpenedPathForLoading = m_mruPath;
-    wxConfigBase*   cfg = Kiface().KifaceSettings();
+    wxString lastOpenedPathForLoading = m_mruPath;
+    FOOTPRINT_EDITOR_SETTINGS* cfg    = GetSettings();
 
-    if( cfg )
-        cfg->Read( EXPORT_IMPORT_LASTPATH_KEY, &lastOpenedPathForLoading );
+    if( !cfg->m_LastImportExportPath.empty() )
+        lastOpenedPathForLoading = cfg->m_LastImportExportPath;
 
     wxFileName fn;
 
@@ -268,11 +267,7 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module( const wxString& aName )
         return NULL;
     }
 
-    if( cfg )    // Save file path
-    {
-        lastOpenedPathForLoading = fn.GetPath();
-        cfg->Write( EXPORT_IMPORT_LASTPATH_KEY, lastOpenedPathForLoading );
-    }
+    cfg->m_LastImportExportPath = lastOpenedPathForLoading;
 
     wxString    moduleName;
     IO_MGR::PCB_FILE_T fileType = detect_file_type( fp, fn.GetFullPath(), &moduleName );
@@ -330,8 +325,8 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module( const wxString& aName )
 
 void FOOTPRINT_EDIT_FRAME::Export_Module( MODULE* aModule )
 {
-    wxFileName      fn;
-    wxConfigBase*   cfg = Kiface().KifaceSettings();
+    wxFileName fn;
+    FOOTPRINT_EDITOR_SETTINGS* cfg = GetSettings();
 
     if( !aModule )
         return;
@@ -342,12 +337,10 @@ void FOOTPRINT_EDIT_FRAME::Export_Module( MODULE* aModule )
 
     fn.SetExt( KiCadFootprintFileExtension );
 
-    if( cfg )
-    {
-        wxString    path;
-        cfg->Read( EXPORT_IMPORT_LASTPATH_KEY, &path, m_mruPath );
-        fn.SetPath( path );
-    }
+    if( !cfg->m_LastImportExportPath.empty() )
+        fn.SetPath( cfg->m_LastImportExportPath );
+    else
+        fn.SetPath( m_mruPath );
 
     wxFileDialog dlg( this, FMT_EXPORT_MODULE, fn.GetPath(), fn.GetFullName(),
                       wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT );
@@ -356,11 +349,7 @@ void FOOTPRINT_EDIT_FRAME::Export_Module( MODULE* aModule )
         return;
 
     fn = dlg.GetPath();
-
-    if( cfg )  // Save file path
-    {
-        cfg->Write( EXPORT_IMPORT_LASTPATH_KEY, fn.GetPath() );
-    }
+    cfg->m_LastImportExportPath = fn.GetPath();
 
     try
     {
@@ -1065,7 +1054,7 @@ MODULE* PCB_BASE_FRAME::CreateNewModule( const wxString& aModuleName )
     BOARD_DESIGN_SETTINGS& settings = GetDesignSettings();
 
     // Update reference:
-    if( settings.m_RefDefaultText.IsEmpty() )
+    if( settings.m_RefDefaultText.empty() )
         module->SetReference( moduleName );
     else
         module->SetReference( settings.m_RefDefaultText );
@@ -1081,7 +1070,7 @@ MODULE* PCB_BASE_FRAME::CreateNewModule( const wxString& aModuleName )
     module->Reference().SetVisible( settings.m_RefDefaultVisibility );
 
     // Set the value field to a default value
-    if( settings.m_ValueDefaultText.IsEmpty() )
+    if( settings.m_ValueDefaultText.empty() )
         module->SetValue( moduleName );
     else
         module->SetValue( settings.m_ValueDefaultText );
diff --git a/pcbnew/footprint_preview_panel.cpp b/pcbnew/footprint_preview_panel.cpp
index 53da5b7059..6424d7dd8d 100644
--- a/pcbnew/footprint_preview_panel.cpp
+++ b/pcbnew/footprint_preview_panel.cpp
@@ -23,9 +23,9 @@
 #include <mutex>
 #include <utility>
 
+#include "pcbnew_settings.h"
 #include <class_board.h>
 #include <class_module.h>
-#include <colors_design_settings.h>
 #include <eda_draw_frame.h>
 #include <footprint_preview_panel.h>
 #include <fp_lib_table.h>
@@ -38,6 +38,7 @@
 #include <pcb_draw_panel_gal.h>
 #include <pcb_edit_frame.h>
 #include <pgm_base.h>
+#include <settings/settings_manager.h>
 #include <view/view.h>
 #include <wx/stattext.h>
 
@@ -266,10 +267,7 @@ FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL( KIWAY* aKiway, wxWindow* aPare
     EnableScrolling( false, false );    // otherwise Zoom Auto disables GAL canvas
 
     m_dummyBoard = std::make_unique<BOARD>();
-    m_colorsSettings = std::make_unique<COLORS_DESIGN_SETTINGS>( FRAME_FOOTPRINT_PREVIEW );
-    m_colorsSettings->Load( Kiface().KifaceSettings() );
-
-    UseColorScheme( m_colorsSettings.get() );
+    UpdateColors();
     SyncLayersVisibility( m_dummyBoard.get() );
 
     Raise();
@@ -393,12 +391,8 @@ FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow*
 {
     PCB_EDIT_FRAME* pcbnew =
             static_cast<PCB_EDIT_FRAME*>( aKiway->Player( FRAME_PCB_EDITOR, false ) );
-    wxConfigBase*   cfg       = Kiface().KifaceSettings();
-    wxConfigBase*   commonCfg = Pgm().CommonSettings();
-    bool            btemp;
-    int             itemp;
-    wxString        msg;
-    COLOR4D         ctemp;
+
+    PCBNEW_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
 
     // Fetch grid & display settings from PCBNew if it's running; otherwise fetch them
     // from PCBNew's config settings.
@@ -415,21 +409,13 @@ FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow*
     }
     else
     {
+
         // Make and populate a new one from config
         gal_opts = std::make_unique<KIGFX::GAL_DISPLAY_OPTIONS>();
-
-        gal_opts->ReadConfig( *commonCfg, *cfg, wxString( PCB_EDIT_FRAME_NAME ), aParent );
+        gal_opts->ReadConfig( *Pgm().GetCommonSettings(), cfg->m_Window, aParent );
     }
 
-#ifdef __WXMAC__
-    // Cairo renderer doesn't handle Retina displays so default to OpenGL
-    EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = (EDA_DRAW_PANEL_GAL::GAL_TYPE)
-                        cfg->ReadLong( CanvasTypeKeyBase, EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL );
-#else
-    EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = (EDA_DRAW_PANEL_GAL::GAL_TYPE)
-                        cfg->ReadLong( CanvasTypeKeyBase, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO );
-#endif
-
+    auto canvasType = static_cast<EDA_DRAW_PANEL_GAL::GAL_TYPE>( cfg->m_Graphics.canvas_type );
     auto panel = new FOOTPRINT_PREVIEW_PANEL( aKiway, aParent, std::move( gal_opts ), canvasType );
 
     if( pcbnew )
@@ -443,19 +429,12 @@ FOOTPRINT_PREVIEW_PANEL* FOOTPRINT_PREVIEW_PANEL::New( KIWAY* aKiway, wxWindow*
     }
     else
     {
-        btemp = cfg->ReadBool( wxString( PCB_EDIT_FRAME_NAME ) + ShowGridEntryKeyword, true );
-        panel->GetGAL()->SetGridVisibility( btemp );
+        panel->GetGAL()->SetGridVisibility( cfg->m_Window.grid.show );
 
         // Read grid size:
         std::unique_ptr<PCB_SCREEN> temp_screen = std::make_unique<PCB_SCREEN>( wxSize() );
-        cfg->Read( wxString( PCB_EDIT_FRAME_NAME ) + LastGridSizeIdKeyword, &itemp, 0L );
-        temp_screen->SetGrid( itemp + ID_POPUP_GRID_LEVEL_1000 );
+        temp_screen->SetGrid( ID_POPUP_GRID_LEVEL_1000 + cfg->m_Window.grid.last_size );
         panel->GetGAL()->SetGridSize( VECTOR2D( temp_screen->GetGridSize() ) );
-
-        // Read grid color:
-        msg = cfg->Read( wxString( PCB_EDIT_FRAME_NAME ) + GridColorEntryKeyword, wxT( "NONE" ) );
-        ctemp.SetFromWxString( msg );
-        panel->GetGAL()->SetGridColor( ctemp );
     }
 
     return panel;
diff --git a/pcbnew/footprint_preview_panel.h b/pcbnew/footprint_preview_panel.h
index 1e7766674e..73c5a84b32 100644
--- a/pcbnew/footprint_preview_panel.h
+++ b/pcbnew/footprint_preview_panel.h
@@ -42,7 +42,6 @@ class IO_MGR;
 class BOARD;
 class FP_LOADER_THREAD;
 class FP_THREAD_IFACE;
-class COLORS_DESIGN_SETTINGS;
 
 
 /**
@@ -101,7 +100,6 @@ private:
 
     std::unique_ptr<BOARD>                      m_dummyBoard;
     std::unique_ptr<KIGFX::GAL_DISPLAY_OPTIONS> m_displayOptions;
-    std::unique_ptr<COLORS_DESIGN_SETTINGS>     m_colorsSettings;
 
     std::shared_ptr<MODULE> m_currentModule;
     LIB_ID                  m_currentFPID;
diff --git a/pcbnew/footprint_viewer_frame.cpp b/pcbnew/footprint_viewer_frame.cpp
index 7b45780e77..83b9bf6c5a 100644
--- a/pcbnew/footprint_viewer_frame.cpp
+++ b/pcbnew/footprint_viewer_frame.cpp
@@ -23,37 +23,40 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <pgm_base.h>
-#include <kiway.h>
-#include <pcb_draw_panel_gal.h>
 #include <3d_viewer/eda_3d_viewer.h>
-#include <dialog_helpers.h>
-#include <msgpanel.h>
-#include <fp_lib_table.h>
-#include <lib_id.h>
-#include <confirm.h>
 #include <bitmaps.h>
-#include <pcb_painter.h>
+#include <board_commit.h>
 #include <class_board.h>
 #include <class_module.h>
+#include <confirm.h>
+#include <dialog_helpers.h>
+#include <eda_pattern_match.h>
+#include <fctsys.h>
+#include <footprint_info.h>
+#include <footprint_viewer_frame.h>
+#include <fp_lib_table.h>
+#include <kiway.h>
+#include <lib_id.h>
+#include <memory>
+#include <msgpanel.h>
+#include <pcb_draw_panel_gal.h>
+#include <pcb_painter.h>
 #include <pcbnew.h>
 #include <pcbnew_id.h>
-#include <footprint_viewer_frame.h>
-#include <footprint_info.h>
-#include <wildcards_and_files_ext.h>
-#include <tool/tool_manager.h>
-#include <tool/tool_dispatcher.h>
+#include <pcbnew_settings.h>
+#include <footprint_editor_settings.h>
+#include <pgm_base.h>
+#include <settings/settings_manager.h>
 #include <tool/action_toolbar.h>
-#include <tool/common_tools.h>
 #include <tool/common_control.h>
-#include <tools/selection_tool.h>
-#include <tools/pcbnew_control.h>
+#include <tool/common_tools.h>
+#include <tool/tool_dispatcher.h>
+#include <tool/tool_manager.h>
 #include <tools/pcb_actions.h>
-#include "tools/pcbnew_picker_tool.h"
-#include <board_commit.h>
-#include <memory>
-#include <eda_pattern_match.h>
+#include <tools/pcbnew_control.h>
+#include <tools/pcbnew_picker_tool.h>
+#include <tools/selection_tool.h>
+#include <wildcards_and_files_ext.h>
 #include <wx/tokenzr.h>
 
 using namespace std::placeholders;
@@ -690,38 +693,44 @@ void FOOTPRINT_VIEWER_FRAME::AddFootprintToPCB( wxCommandEvent& aEvent )
 }
 
 
-void FOOTPRINT_VIEWER_FRAME::LoadSettings( wxConfigBase* aCfg )
+void FOOTPRINT_VIEWER_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+
     PCB_BASE_FRAME::LoadSettings( aCfg );
 
     // Fetch grid settings from Footprint Editor
-    wxString footprintEditor = FOOTPRINT_EDIT_FRAME_NAME;
-    bool     btmp;
-    COLOR4D  wtmp;
+    auto fpedit = Pgm().GetSettingsManager().GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>();
 
-    if( aCfg->Read( footprintEditor + ShowGridEntryKeyword, &btmp ) )
-        SetGridVisibility( btmp );
+    SetGridVisibility( fpedit->m_Window.grid.show );
 
-    if( wtmp.SetFromWxString( aCfg->Read( footprintEditor + GridColorEntryKeyword,
-                                          wxT( "NONE" ) ) ) )
-        SetGridColor( wtmp );
+    GetGalDisplayOptions().ReadWindowSettings( fpedit->m_Window );
 
-    // Grid shape, etc.
-    GetGalDisplayOptions().ReadAppConfig( *aCfg, footprintEditor );
-
-    m_configSettings.Load( aCfg );  // mainly, load the color config
-
-    aCfg->Read( ConfigBaseName() + AUTO_ZOOM_KEY, &m_autoZoom, true );
-    aCfg->Read( ConfigBaseName() + ZOOM_KEY, &m_lastZoom, 10.0 );
+    m_autoZoom = cfg->m_FootprintViewer.auto_zoom;
+    m_lastZoom = cfg->m_FootprintViewer.zoom;
 }
 
 
-void FOOTPRINT_VIEWER_FRAME::SaveSettings( wxConfigBase* aCfg )
+void FOOTPRINT_VIEWER_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
-    PCB_BASE_FRAME::SaveSettings( aCfg );
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
 
-    aCfg->Write( ConfigBaseName() + AUTO_ZOOM_KEY, m_autoZoom );
-    aCfg->Write( ConfigBaseName() + ZOOM_KEY, GetCanvas()->GetView()->GetScale() );
+    // We don't want to store anything other than the window settings
+    EDA_BASE_FRAME::SaveSettings( cfg );
+
+    cfg->m_FootprintViewer.auto_zoom = m_autoZoom;
+    cfg->m_FootprintViewer.zoom      = GetCanvas()->GetView()->GetScale();
+}
+
+
+WINDOW_SETTINGS* FOOTPRINT_VIEWER_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
+{
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+
+    return &cfg->m_FootprintViewer;
 }
 
 
@@ -857,7 +866,7 @@ void FOOTPRINT_VIEWER_FRAME::Update3DView( bool aForceReload, const wxString* aT
 
 COLOR4D FOOTPRINT_VIEWER_FRAME::GetGridColor()
 {
-    return Settings().Colors().GetItemColor( LAYER_GRID );
+    return ColorSettings()->GetColor( LAYER_GRID );
 }
 
 
@@ -961,7 +970,7 @@ void FOOTPRINT_VIEWER_FRAME::ApplyDisplaySettingsToGAL()
 
 void FOOTPRINT_VIEWER_FRAME::updateView()
 {
-    GetCanvas()->UseColorScheme( &Settings().Colors() );
+    GetCanvas()->UpdateColors();
     GetCanvas()->DisplayBoard( GetBoard() );
 
     m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
diff --git a/pcbnew/footprint_viewer_frame.h b/pcbnew/footprint_viewer_frame.h
index a8c0ff8235..69a5413c31 100644
--- a/pcbnew/footprint_viewer_frame.h
+++ b/pcbnew/footprint_viewer_frame.h
@@ -50,8 +50,6 @@ protected:
 public:
     ~FOOTPRINT_VIEWER_FRAME();
 
-    PCB_GENERAL_SETTINGS& GetConfigSettings() { return m_configSettings; }
-
     /// Updates the GAL with display settings changes
     void ApplyDisplaySettingsToGAL();
 
@@ -128,8 +126,11 @@ private:
 
     void InstallDisplayOptions( wxCommandEvent& aEvent );
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-    void SaveSettings( wxConfigBase* aCfg ) override;
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
+
+    WINDOW_SETTINGS* GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override;
+
     void CommonSettingsChanged( bool aEnvVarsChanged ) override;
 
     /**
diff --git a/pcbnew/footprint_wizard_frame.cpp b/pcbnew/footprint_wizard_frame.cpp
index 57feb74dde..cfdce07e43 100644
--- a/pcbnew/footprint_wizard_frame.cpp
+++ b/pcbnew/footprint_wizard_frame.cpp
@@ -36,6 +36,7 @@
 #include <class_board.h>
 #include <footprint_edit_frame.h>
 #include <pcbnew_id.h>
+#include <pcbnew_settings.h>
 #include "footprint_wizard_frame.h"
 #include <wx/tokenzr.h>
 #include <wx/numformatter.h>
@@ -291,7 +292,7 @@ void FOOTPRINT_WIZARD_FRAME::OnSize( wxSizeEvent& SizeEv )
 
 void FOOTPRINT_WIZARD_FRAME::updateView()
 {
-    GetCanvas()->UseColorScheme( &Settings().Colors() );
+    GetCanvas()->UpdateColors();
     GetCanvas()->DisplayBoard( GetBoard() );
     m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
     m_toolManager->RunAction( ACTIONS::zoomFitScreen, true );
@@ -506,22 +507,33 @@ void FOOTPRINT_WIZARD_FRAME::ClickOnPageList( wxCommandEvent& event )
 }
 
 
-#define AUI_PERSPECTIVE_KEY  wxT( "Fpwizard_auiPerspective" )
-
-
-void FOOTPRINT_WIZARD_FRAME::LoadSettings( wxConfigBase* aCfg )
+void FOOTPRINT_WIZARD_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
-    EDA_DRAW_FRAME::LoadSettings( aCfg );
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
 
-    aCfg->Read( AUI_PERSPECTIVE_KEY, &m_auiPerspective );
+    EDA_DRAW_FRAME::LoadSettings( cfg );
+
+    m_auiPerspective = cfg->m_FootprintViewer.perspective;
 }
 
 
-void FOOTPRINT_WIZARD_FRAME::SaveSettings( wxConfigBase* aCfg )
+void FOOTPRINT_WIZARD_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
-    EDA_DRAW_FRAME::SaveSettings( aCfg );
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
 
-    aCfg->Write( AUI_PERSPECTIVE_KEY, m_auimgr.SavePerspective() );
+    EDA_DRAW_FRAME::SaveSettings( cfg );
+
+    cfg->m_FootprintViewer.perspective = m_auimgr.SavePerspective().ToStdString();
+}
+
+
+WINDOW_SETTINGS* FOOTPRINT_WIZARD_FRAME::GetWindowSettings( APP_SETTINGS_BASE* aCfg )
+{
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+    return &cfg->m_FootprintWizard;
 }
 
 
diff --git a/pcbnew/footprint_wizard_frame.h b/pcbnew/footprint_wizard_frame.h
index c63d520802..b689739b74 100644
--- a/pcbnew/footprint_wizard_frame.h
+++ b/pcbnew/footprint_wizard_frame.h
@@ -180,14 +180,16 @@ private:
     void                ReCreateVToolbar() override;
     void                ClickOnPageList( wxCommandEvent& event );
 
-    void                LoadSettings( wxConfigBase* aCfg ) override;
-    void                SaveSettings( wxConfigBase* aCfg ) override;
+    void                LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
+    void                SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
-    /**
-     * Function OnActivate
-     * is called when the frame frame is activate to reload the libraries and component lists
-     * that can be changed by the schematic editor or the library editor.
-     */
+    WINDOW_SETTINGS*    GetWindowSettings( APP_SETTINGS_BASE* aCfg ) override;
+
+            /**
+             * Function OnActivate
+             * is called when the frame frame is activate to reload the libraries and component lists
+             * that can be changed by the schematic editor or the library editor.
+             */
     void                OnActivate( wxActivateEvent& event );
 
     void                SelectCurrentWizard( wxCommandEvent& event );
diff --git a/pcbnew/grid_layer_box_helpers.cpp b/pcbnew/grid_layer_box_helpers.cpp
index e4de221e46..f068bdf000 100644
--- a/pcbnew/grid_layer_box_helpers.cpp
+++ b/pcbnew/grid_layer_box_helpers.cpp
@@ -23,11 +23,12 @@
 
 #include <grid_layer_box_helpers.h>
 
-#include <pcb_edit_frame.h>
 #include <class_board.h>
-#include <wx/textctrl.h>
-#include <widgets/layer_box_selector.h>
+#include <pcb_edit_frame.h>
 #include <pcb_layer_box_selector.h>
+#include <settings/color_settings.h>
+#include <widgets/layer_box_selector.h>
+#include <wx/textctrl.h>
 
 
 //-------- Custom wxGridCellRenderers --------------------------------------------------
@@ -57,10 +58,10 @@ void GRID_CELL_LAYER_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC&
 
     // draw the swatch
     wxBitmap bitmap( 14, 14 );
-    const COLORS_DESIGN_SETTINGS& cds = m_frame->Settings().Colors();
+    COLOR_SETTINGS* cs = m_frame->ColorSettings();
     LAYER_SELECTOR::DrawColorSwatch( bitmap,
-                                     cds.GetLayerColor( ToLAYER_ID( LAYER_PCB_BACKGROUND ) ),
-                                     cds.GetLayerColor( ToLAYER_ID( value ) ) );
+                                     cs->GetColor( ToLAYER_ID( LAYER_PCB_BACKGROUND ) ),
+                                     cs->GetColor( ToLAYER_ID( value ) ) );
     aDC.DrawBitmap( bitmap, rect.GetLeft() + 4, rect.GetTop() + 3, true );
 
     // draw the text
diff --git a/pcbnew/import_gfx/dialog_import_gfx.cpp b/pcbnew/import_gfx/dialog_import_gfx.cpp
index cb555db7ee..9ecee68c0c 100644
--- a/pcbnew/import_gfx/dialog_import_gfx.cpp
+++ b/pcbnew/import_gfx/dialog_import_gfx.cpp
@@ -34,20 +34,6 @@
 
 #include <memory>
 
-// Configuration path (group) to store entry keys below.
-#define IMPORT_GFX_GROUP                        "ImportGraphics"
-
-// Entry keys to store setup in config
-#define IMPORT_GFX_LAYER_OPTION_KEY             "BoardLayer"
-#define IMPORT_GFX_PLACEMENT_INTERACTIVE_KEY    "InteractivePlacement"
-#define IMPORT_GFX_LAST_FILE_KEY                "LastFile"
-#define IMPORT_GFX_POSITION_UNITS_KEY           "PositionUnits"
-#define IMPORT_GFX_POSITION_X_KEY               "PositionX"
-#define IMPORT_GFX_POSITION_Y_KEY               "PositionY"
-#define IMPORT_GFX_LINEWIDTH_UNITS_KEY          "LineWidthUnits"
-#define IMPORT_GFX_LINEWIDTH_KEY                "LineWidth"
-
-
 // Static members of DIALOG_IMPORT_GFX, to remember the user's choices during the session
 wxString DIALOG_IMPORT_GFX::m_filename;
 bool DIALOG_IMPORT_GFX::m_placementInteractive = true;
@@ -83,27 +69,22 @@ DIALOG_IMPORT_GFX::DIALOG_IMPORT_GFX( PCB_BASE_FRAME* aParent, bool aImportAsFoo
         m_gfxImportMgr = std::make_unique<GRAPHICS_IMPORT_MGR>( blacklist );
     }
 
-    m_config = Kiface().KifaceSettings();
     m_originUnits = 0;
     m_origin.x = 0.0;              // always in mm
     m_origin.y = 0.0;              // always in mm
     m_lineWidth = 0.2;             // always in mm
     m_lineWidthUnits = 0;
 
-    if( m_config )
-    {
-        wxString tmp = m_config->GetPath();
-        m_config->SetPath( IMPORT_GFX_GROUP );
-        m_layer = m_config->Read( IMPORT_GFX_LAYER_OPTION_KEY, (long)Dwgs_User );
-        m_placementInteractive = m_config->Read( IMPORT_GFX_PLACEMENT_INTERACTIVE_KEY, true );
-        m_filename =  m_config->Read( IMPORT_GFX_LAST_FILE_KEY, wxEmptyString );
-        m_config->Read( IMPORT_GFX_LINEWIDTH_KEY, &m_lineWidth, 0.2 );
-        m_config->Read( IMPORT_GFX_LINEWIDTH_UNITS_KEY, &m_lineWidthUnits, 0 );
-        m_config->Read( IMPORT_GFX_POSITION_UNITS_KEY, &m_originUnits, 0 );
-        m_config->Read( IMPORT_GFX_POSITION_X_KEY, &m_origin.x, 0.0 );
-        m_config->Read( IMPORT_GFX_POSITION_Y_KEY, &m_origin.y, 0.0 );
-        m_config->SetPath( tmp );
-    }
+    auto cfg = m_parent->GetSettings();
+
+    m_layer                = cfg->m_ImportGraphics.layer;
+    m_placementInteractive = cfg->m_ImportGraphics.interactive_placement;
+    m_filename             = cfg->m_ImportGraphics.last_file;
+    m_lineWidth            = cfg->m_ImportGraphics.line_width;
+    m_lineWidthUnits       = cfg->m_ImportGraphics.line_width_units;
+    m_originUnits          = cfg->m_ImportGraphics.origin_units;
+    m_origin.x             = cfg->m_ImportGraphics.origin_x;
+    m_origin.y             = cfg->m_ImportGraphics.origin_y;
 
     m_choiceUnitLineWidth->SetSelection( m_lineWidthUnits );
     showPCBdefaultLineWidth();
@@ -139,22 +120,16 @@ DIALOG_IMPORT_GFX::DIALOG_IMPORT_GFX( PCB_BASE_FRAME* aParent, bool aImportAsFoo
 
 DIALOG_IMPORT_GFX::~DIALOG_IMPORT_GFX()
 {
-    if( m_config )
-    {
-        wxString tmp = m_config->GetPath();
-        m_config->SetPath( IMPORT_GFX_GROUP );
-        m_config->Write( IMPORT_GFX_LAYER_OPTION_KEY, (long)m_layer );
-        m_config->Write( IMPORT_GFX_PLACEMENT_INTERACTIVE_KEY, m_placementInteractive );
-        m_config->Write( IMPORT_GFX_LAST_FILE_KEY, m_filename );
+    auto cfg = m_parent->GetSettings();
 
-        m_config->Write( IMPORT_GFX_POSITION_UNITS_KEY, m_originUnits );
-        m_config->Write( IMPORT_GFX_POSITION_X_KEY, m_origin.x );
-        m_config->Write( IMPORT_GFX_POSITION_Y_KEY, m_origin.y );
-
-        m_config->Write( IMPORT_GFX_LINEWIDTH_KEY, m_lineWidth );
-        m_config->Write( IMPORT_GFX_LINEWIDTH_UNITS_KEY, m_lineWidthUnits );
-        m_config->SetPath( tmp );
-    }
+    cfg->m_ImportGraphics.layer                 = m_layer;
+    cfg->m_ImportGraphics.interactive_placement = m_placementInteractive;
+    cfg->m_ImportGraphics.last_file             = m_filename;
+    cfg->m_ImportGraphics.line_width            = m_lineWidth;
+    cfg->m_ImportGraphics.line_width_units      = m_lineWidthUnits;
+    cfg->m_ImportGraphics.origin_units          = m_originUnits;
+    cfg->m_ImportGraphics.origin_x              = m_origin.x;
+    cfg->m_ImportGraphics.origin_y              = m_origin.y;
 }
 
 
diff --git a/pcbnew/import_gfx/dialog_import_gfx.h b/pcbnew/import_gfx/dialog_import_gfx.h
index 980f784747..5f5397493f 100644
--- a/pcbnew/import_gfx/dialog_import_gfx.h
+++ b/pcbnew/import_gfx/dialog_import_gfx.h
@@ -26,6 +26,7 @@
 #define __DIALOG_IMPORT_GFX_H__
 
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include "dialog_import_gfx_base.h"
 #include <import_gfx/graphics_importer_pcbnew.h>
 
@@ -59,7 +60,6 @@ public:
 
 private:
     PCB_BASE_FRAME*      m_parent;
-    wxConfigBase*        m_config;              // Current config
     std::unique_ptr<GRAPHICS_IMPORTER_PCBNEW> m_importer;
     std::unique_ptr<GRAPHICS_IMPORT_MGR>      m_gfxImportMgr;
     static int           m_originUnits;
diff --git a/pcbnew/invoke_pcb_dialog.h b/pcbnew/invoke_pcb_dialog.h
index 1ceb6cbd36..f8190259f6 100644
--- a/pcbnew/invoke_pcb_dialog.h
+++ b/pcbnew/invoke_pcb_dialog.h
@@ -98,10 +98,10 @@ void InvokePluginOptionsEditor( wxWindow* aCaller, const wxString& aNickname,
 /**
  * Function InvokeExportSVG
  * shows the Export SVG dialog
- * @param aCaller is the PCB_BASE_FRAME which is invoking the dialog.
+ * @param aCaller is the PCB_EDIT_FRAME which is invoking the dialog.
  * @param aBoard is the currently edited board.
  * @return bool - true if user pressed OK (did not abort), else false.
  */
-bool InvokeExportSVG( PCB_BASE_FRAME* aCaller, BOARD* aBoard );
+bool InvokeExportSVG( PCB_EDIT_FRAME* aCaller, BOARD* aBoard );
 
 #endif  // INVOKE_A_DIALOG_H_
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index acc127ecc9..4ebfd04b58 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -43,6 +43,7 @@
 #include <zones.h>
 #include <kicad_plugin.h>
 #include <pcb_parser.h>
+#include <pcbnew_settings.h>
 #include <wx/dir.h>
 #include <wx/filename.h>
 #include <wx/wfstream.h>
@@ -52,7 +53,7 @@
 #include <convert_basic_shapes_to_polygon.h>    // for enum RECT_CHAMFER_POSITIONS definition
 #include <kiface_i.h>
 
-#include <advanced_config.h>    // for pad pin function and pad property feature management
+#include <advanced_config.h> // for pad pin function and pad property feature management
 
 using namespace PCB_KEYS_T;
 
@@ -2275,10 +2276,12 @@ void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootpri
 
     if( module->GetLayer() != F_Cu )
     {
-	if( m_board != nullptr )
-            module->Flip( module->GetPosition(), m_board->GeneralSettings().m_FlipLeftRight );
-	else
-	   module->Flip( module->GetPosition(), false );
+        auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() );
+
+        if( cfg != nullptr )
+            module->Flip( module->GetPosition(), cfg->m_FlipLeftRight );
+        else
+            module->Flip( module->GetPosition(), false );
     }
 
     wxLogTrace( traceKicadPcbPlugin, wxT( "Creating s-expr footprint file '%s'." ), fullPath );
diff --git a/pcbnew/load_select_footprint.cpp b/pcbnew/load_select_footprint.cpp
index 62d4851fa7..97bd3cdf99 100644
--- a/pcbnew/load_select_footprint.cpp
+++ b/pcbnew/load_select_footprint.cpp
@@ -26,36 +26,32 @@
 #include <functional>
 using namespace std::placeholders;
 
-#include <fctsys.h>
-#include <pcb_draw_panel_gal.h>
-#include <confirm.h>
-#include <eda_doc.h>
-#include <kicad_string.h>
-#include <pgm_base.h>
-#include <kiway.h>
-#include <view/view_controls.h>
-#include <pcb_edit_frame.h>
-#include <dialog_helpers.h>
-#include <filter_reader.h>
-#include <gr_basic.h>
-#include <macros.h>
-#include <fp_lib_table.h>
-#include <lib_id.h>
-#include <footprint_tree_pane.h>
 #include <class_board.h>
 #include <class_module.h>
-#include <io_mgr.h>
+#include <confirm.h>
 #include <connectivity/connectivity_data.h>
-#include <pcbnew.h>
-#include <footprint_edit_frame.h>
-#include <footprint_info.h>
-#include <footprint_info_impl.h>
 #include <dialog_choose_footprint.h>
 #include <dialog_get_footprint_by_name.h>
+#include <dialog_helpers.h>
+#include <footprint_edit_frame.h>
+#include <footprint_info_impl.h>
+#include <footprint_tree_pane.h>
 #include <footprint_viewer_frame.h>
-#include <wildcards_and_files_ext.h>
-#include <widgets/progress_reporter.h>
+#include <fp_lib_table.h>
+#include <io_mgr.h>
+#include <kicad_string.h>
+#include <kiway.h>
+#include <lib_id.h>
+#include <macros.h>
+#include <pcb_draw_panel_gal.h>
+#include <pcb_edit_frame.h>
+#include <pcbnew.h>
+#include <pcbnew_settings.h>
+#include <pgm_base.h>
+#include <view/view_controls.h>
 #include <widgets/lib_tree.h>
+#include <widgets/progress_reporter.h>
+
 #include "fp_tree_model_adapter.h"
 
 
diff --git a/pcbnew/menubar_footprint_editor.cpp b/pcbnew/menubar_footprint_editor.cpp
index a7a82653f8..1c2709cbff 100644
--- a/pcbnew/menubar_footprint_editor.cpp
+++ b/pcbnew/menubar_footprint_editor.cpp
@@ -26,17 +26,17 @@
 
 #include "footprint_edit_frame.h"
 
-#include <advanced_config.h>
-#include <menus_helpers.h>
-#include <pgm_base.h>
-#include <tool/tool_manager.h>
-#include <tool/conditional_menu.h>
-#include <tool/actions.h>
-#include <tools/selection_tool.h>
-#include <tools/pcb_actions.h>
 #include "help_common_strings.h"
 #include "pcbnew.h"
 #include "pcbnew_id.h"
+#include <menus_helpers.h>
+#include <pgm_base.h>
+#include <advanced_config.h>
+#include <tool/actions.h>
+#include <tool/conditional_menu.h>
+#include <tool/tool_manager.h>
+#include <tools/pcb_actions.h>
+#include <tools/selection_tool.h>
 
 
 void FOOTPRINT_EDIT_FRAME::ReCreateMenuBar()
diff --git a/pcbnew/menubar_pcb_editor.cpp b/pcbnew/menubar_pcb_editor.cpp
index 28a330a70c..ed5271d60c 100644
--- a/pcbnew/menubar_pcb_editor.cpp
+++ b/pcbnew/menubar_pcb_editor.cpp
@@ -26,20 +26,20 @@
 
 #include <pcb_edit_frame.h>
 
-#include <advanced_config.h>
+#include "help_common_strings.h"
+#include "pcbnew.h"
+#include "pcbnew_id.h"
 #include <filehistory.h>
 #include <kiface_i.h>
 #include <menus_helpers.h>
 #include <pgm_base.h>
-#include <tool/tool_manager.h>
-#include <tool/conditional_menu.h>
+#include <advanced_config.h>
 #include <tool/actions.h>
+#include <tool/conditional_menu.h>
 #include <tool/selection_conditions.h>
-#include <tools/selection_tool.h>
+#include <tool/tool_manager.h>
 #include <tools/pcb_actions.h>
-#include "help_common_strings.h"
-#include "pcbnew.h"
-#include "pcbnew_id.h"
+#include <tools/selection_tool.h>
 
 
 void PCB_EDIT_FRAME::ReCreateMenuBar()
diff --git a/pcbnew/pad_print_functions.cpp b/pcbnew/pad_print_functions.cpp
index b9e5caea1e..2c5deaf803 100644
--- a/pcbnew/pad_print_functions.cpp
+++ b/pcbnew/pad_print_functions.cpp
@@ -33,6 +33,7 @@
 #include <gr_basic.h>
 #include <math/util.h>      // for KiROUND
 #include <layers_id_colors_and_visibility.h>
+#include <settings/color_settings.h>
 #include <pcb_edit_frame.h>
 #include <pcb_screen.h>
 #include <pcbnew.h>
@@ -79,8 +80,6 @@ void D_PAD::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOffset )
 
     BOARD* brd = GetBoard();
 
-    const auto& cds = aFrame->Settings().Colors();
-
     bool   frontVisible = brd->IsElementVisible( LAYER_PAD_FR );
     bool   backVisible  = brd->IsElementVisible( LAYER_PAD_BK );
 
@@ -110,12 +109,12 @@ void D_PAD::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOffset )
 
     if( m_layerMask[F_Cu] )
     {
-        color = cds.GetItemColor( LAYER_PAD_FR );
+        color = aFrame->ColorSettings()->GetColor( LAYER_PAD_FR );
     }
 
     if( m_layerMask[B_Cu] )
     {
-        color = color.LegacyMix( cds.GetItemColor( LAYER_PAD_BK ) );
+        color = color.LegacyMix( aFrame->ColorSettings()->GetColor( LAYER_PAD_BK ) );
     }
 
     if( color == BLACK ) // Not on a visible copper layer (i.e. still nothing to show)
@@ -135,7 +134,7 @@ void D_PAD::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOffset )
             break;
 
         default:
-            color = cds.GetLayerColor( pad_layer );
+            color = aFrame->ColorSettings()->GetColor( pad_layer );
         }
     }
 
@@ -161,17 +160,17 @@ void D_PAD::Print( PCB_BASE_FRAME* aFrame, wxDC* aDC, const wxPoint& aOffset )
         brd->IsElementVisible( LAYER_NON_PLATEDHOLES ) )
     {
         drawInfo.m_ShowNotPlatedHole = true;
-        drawInfo.m_NPHoleColor = cds.GetItemColor( LAYER_NON_PLATEDHOLES );
+        drawInfo.m_NPHoleColor = aFrame->ColorSettings()->GetColor( LAYER_NON_PLATEDHOLES );
     }
     // Don't let pads that *should* be NPTHs get lost
     else if ( PadShouldBeNPTH() )
     {
         drawInfo.m_ShowNotPlatedHole = true;
-        drawInfo.m_NPHoleColor = cds.GetItemColor( LAYER_MOD_TEXT_INVISIBLE );
+        drawInfo.m_NPHoleColor = aFrame->ColorSettings()->GetColor( LAYER_MOD_TEXT_INVISIBLE );
     }
 
     drawInfo.m_Color          = color;
-    drawInfo.m_NoNetMarkColor = cds.GetItemColor( LAYER_NO_CONNECTS );
+    drawInfo.m_NoNetMarkColor = aFrame->ColorSettings()->GetColor( LAYER_NO_CONNECTS );
     drawInfo.m_Mask_margin    = mask_margin;
     drawInfo.m_ShowNCMark     = brd->IsElementVisible( LAYER_NO_CONNECTS );
     drawInfo.m_IsPrinting     = screen->m_IsPrinting;
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcad2kicad_common.cpp b/pcbnew/pcad2kicadpcb_plugin/pcad2kicad_common.cpp
index 93409d1663..20d77e8081 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcad2kicad_common.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcad2kicad_common.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 #include <wx/regex.h>
 
 #include <common.h>
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb.cpp
index c42add6459..7857d0d7e9 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_arc.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_arc.cpp
index b15a97bac2..16cd83e446 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_arc.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_arc.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 #include <math/util.h>      // for KiROUND
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_component.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_component.cpp
index 44f5cd9467..d47cf9373c 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_component.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_component.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_copper_pour.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_copper_pour.cpp
index c438744187..1ea1e16ae1 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_copper_pour.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_copper_pour.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_cutout.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_cutout.cpp
index 39a0d6fca4..4b407182a7 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_cutout.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_cutout.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <pcb_cutout.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_keepout.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_keepout.cpp
index 8aee07fdb4..5c808db9cc 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_keepout.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_keepout.cpp
@@ -27,7 +27,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_line.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_line.cpp
index 25383146fd..a36b90e9de 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_line.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_line.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_module.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_module.cpp
index 1d5ff6fe5d..f44ec456f7 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_module.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_module.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_net.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_net.cpp
index c1dc5ee6df..b98fe2a0af 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_net.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_net.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <pcb_net.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_pad.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_pad.cpp
index da5139afc7..b83ed56c37 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_pad.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_pad.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 #include <trigo.h>
 
 #include <pcb_pad.h>
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_pad_shape.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_pad_shape.cpp
index 82ca1c92e5..c5c41bbbc8 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_pad_shape.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_pad_shape.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_plane.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_plane.cpp
index d4075f61c6..da1c04aa60 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_plane.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_plane.cpp
@@ -27,7 +27,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_polygon.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_polygon.cpp
index ce2450a1f6..230bf4e9e3 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_polygon.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_polygon.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 #include <math/util.h>      // for KiROUND
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_text.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_text.cpp
index a657e36bee..037d4ef9ef 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_text.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_text.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <common.h>
 
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_via.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_via.cpp
index 92ed1e4426..87885cd69a 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_via.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_via.cpp
@@ -28,7 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
 
 #include <pcb_via.h>
 #include <pcb_via_shape.h>
diff --git a/pcbnew/pcad2kicadpcb_plugin/pcb_via_shape.cpp b/pcbnew/pcad2kicadpcb_plugin/pcb_via_shape.cpp
index 3aeedf7da5..ebdf1f3090 100644
--- a/pcbnew/pcad2kicadpcb_plugin/pcb_via_shape.cpp
+++ b/pcbnew/pcad2kicadpcb_plugin/pcb_via_shape.cpp
@@ -28,8 +28,6 @@
  */
 
 #include <wx/wx.h>
-#include <wx/config.h>
-
 #include <common.h>
 
 #include <pcb_via_shape.h>
diff --git a/pcbnew/pcb_base_edit_frame.cpp b/pcbnew/pcb_base_edit_frame.cpp
index 4ec0ed1adf..5e9d8185fa 100644
--- a/pcbnew/pcb_base_edit_frame.cpp
+++ b/pcbnew/pcb_base_edit_frame.cpp
@@ -31,6 +31,7 @@
 #include <view/view.h>
 #include "footprint_info_impl.h"
 #include <project.h>
+#include <settings/color_settings.h>
 #include <tools/pcb_actions.h>
 
 PCB_BASE_EDIT_FRAME::PCB_BASE_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent,
@@ -97,7 +98,8 @@ void PCB_BASE_EDIT_FRAME::SetBoard( BOARD* aBoard )
     if( m_toolManager )
     {
         GetCanvas()->DisplayBoard( aBoard );
-        GetCanvas()->UseColorScheme( &Settings().Colors() );
+
+        GetCanvas()->UpdateColors();
         m_toolManager->SetEnvironment( aBoard, GetCanvas()->GetView(),
                                        GetCanvas()->GetViewControls(), this );
 
diff --git a/pcbnew/pcb_base_frame.cpp b/pcbnew/pcb_base_frame.cpp
index 4409a4c2aa..cae2d297ce 100644
--- a/pcbnew/pcb_base_frame.cpp
+++ b/pcbnew/pcb_base_frame.cpp
@@ -48,25 +48,12 @@
 #include <math/vector2d.h>
 #include <trigo.h>
 #include <pcb_painter.h>
+#include <settings/settings_manager.h>
+#include <pcbnew_settings.h>
 #include <tool/tool_manager.h>
 #include <tool/tool_dispatcher.h>
 #include <tools/pcb_actions.h>
 
-const wxChar PCB_BASE_FRAME::AUTO_ZOOM_KEY[] = wxT( "AutoZoom" );
-const wxChar PCB_BASE_FRAME::ZOOM_KEY[] = wxT( "Zoom" );
-
-// Configuration entry names.
-static const wxChar UserGridSizeXEntry[] = wxT( "PcbUserGrid_X" );
-static const wxChar UserGridSizeYEntry[] = wxT( "PcbUserGrid_Y" );
-static const wxChar UserGridUnitsEntry[] = wxT( "PcbUserGrid_Unit" );
-static const wxChar DisplayPadFillEntry[] = wxT( "DiPadFi" );
-static const wxChar DisplayViaFillEntry[] = wxT( "DiViaFi" );
-static const wxChar DisplayPadNumberEntry[] = wxT( "DiPadNu" );
-static const wxChar DisplayModuleEdgeEntry[] = wxT( "DiModEd" );
-static const wxChar DisplayModuleTextEntry[] = wxT( "DiModTx" );
-static const wxChar FastGrid1Entry[] = wxT( "FastGrid1" );
-static const wxChar FastGrid2Entry[] = wxT( "FastGrid2" );
-
 
 BEGIN_EVENT_TABLE( PCB_BASE_FRAME, EDA_DRAW_FRAME )
     EVT_TOOL( ID_TB_OPTIONS_SHOW_PADS_SKETCH, PCB_BASE_FRAME::OnTogglePadDrawMode )
@@ -85,8 +72,7 @@ PCB_BASE_FRAME::PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
         const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
         long aStyle, const wxString & aFrameName ) :
     EDA_DRAW_FRAME( aKiway, aParent, aFrameType, aTitle, aPos, aSize, aStyle, aFrameName ),
-    m_Pcb( nullptr ),
-    m_configSettings( aFrameType )
+    m_Pcb( nullptr )
 {
     m_UserGridSize        = wxPoint( (int) 10 * IU_PER_MILS, (int) 10 * IU_PER_MILS );
 
@@ -97,6 +83,8 @@ PCB_BASE_FRAME::PCB_BASE_FRAME( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrame
                                         // when the screen shows a 1:1 image
                                         // obviously depends on the monitor,
                                         // but this is an acceptable value
+
+    m_Settings = static_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() );
 }
 
 
@@ -171,7 +159,7 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard )
     {
         delete m_Pcb;
         m_Pcb = aBoard;
-        m_Pcb->SetGeneralSettings( &Settings() );
+        m_Pcb->SetGeneralSettings( m_Settings );
     }
 }
 
@@ -191,7 +179,7 @@ void PCB_BASE_FRAME::AddModuleToBoard( MODULE* module )
         // Put it on FRONT layer (note that it might be stored flipped if the lib is an archive
         // built from a board)
         if( module->IsFlipped() )
-            module->Flip( module->GetPosition(), m_configSettings.m_FlipLeftRight );
+            module->Flip( module->GetPosition(), m_Settings->m_FlipLeftRight );
 
         // Place it in orientation 0 even if it is not saved with orientation 0 in lib (note that
         // it might be stored in another orientation if the lib is an archive built from a board)
@@ -284,6 +272,12 @@ void PCB_BASE_FRAME::SetDesignSettings( const BOARD_DESIGN_SETTINGS& aSettings )
 }
 
 
+COLOR_SETTINGS* PCB_BASE_FRAME::ColorSettings()
+{
+    return Pgm().GetSettingsManager().GetColorSettings();
+}
+
+
 void PCB_BASE_FRAME::SetDrawBgColor( COLOR4D aColor )
 {
     m_drawBgColor= aColor;
@@ -684,58 +678,52 @@ void PCB_BASE_FRAME::unitsChangeRefresh()
 }
 
 
-void PCB_BASE_FRAME::LoadSettings( wxConfigBase* aCfg )
+void PCB_BASE_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_DRAW_FRAME::LoadSettings( aCfg );
 
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+
     // Ensure grid id is an existent grid id:
     if( (m_LastGridSizeId <= 0) ||
         (m_LastGridSizeId > (ID_POPUP_GRID_USER - ID_POPUP_GRID_LEVEL_1000)) )
         m_LastGridSizeId = ID_POPUP_GRID_LEVEL_500 - ID_POPUP_GRID_LEVEL_1000;
 
-    wxString baseCfgName = GetName();
+    EDA_UNITS userGridUnits = static_cast<EDA_UNITS>( cfg->m_UserGrid.units );
+    m_UserGridSize.x = (int) From_User_Unit( userGridUnits, cfg->m_UserGrid.size_x );
+    m_UserGridSize.y = (int) From_User_Unit( userGridUnits, cfg->m_UserGrid.size_y );
 
-    EDA_UNITS userGridUnits;
-    aCfg->Read( baseCfgName + UserGridUnitsEntry, (int*) &userGridUnits, (int) EDA_UNITS::INCHES );
+    m_DisplayOptions = cfg->m_Display;
+    m_PolarCoords = cfg->m_PolarCoords;
 
-    double tmp;
-    aCfg->Read( baseCfgName + UserGridSizeXEntry, &tmp, 0.01 );
-    m_UserGridSize.x = (int) From_User_Unit( userGridUnits, tmp );
-
-    aCfg->Read( baseCfgName + UserGridSizeYEntry, &tmp, 0.01 );
-    m_UserGridSize.y = (int) From_User_Unit( userGridUnits, tmp );
-
-    aCfg->Read( baseCfgName + DisplayPadFillEntry, &m_DisplayOptions.m_DisplayPadFill, true );
-    aCfg->Read( baseCfgName + DisplayViaFillEntry, &m_DisplayOptions.m_DisplayViaFill, true );
-    aCfg->Read( baseCfgName + DisplayPadNumberEntry, &m_DisplayOptions.m_DisplayPadNum, true );
-    aCfg->Read( baseCfgName + DisplayModuleEdgeEntry, &m_DisplayOptions.m_DisplayModEdgeFill, true );
-
-    long itmp;
-    aCfg->Read( baseCfgName + FastGrid1Entry, &itmp, ( long )0);
-    m_FastGrid1 = itmp;
-    aCfg->Read( baseCfgName + FastGrid2Entry, &itmp, ( long )0);
-    m_FastGrid2 = itmp;
-
-    aCfg->Read( baseCfgName + DisplayModuleTextEntry, &m_DisplayOptions.m_DisplayModTextFill, true );
+    m_FastGrid1 = cfg->m_FastGrid1;
+    m_FastGrid2 = cfg->m_FastGrid2;
 }
 
 
-void PCB_BASE_FRAME::SaveSettings( wxConfigBase* aCfg )
+void PCB_BASE_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
     EDA_DRAW_FRAME::SaveSettings( aCfg );
 
-    wxString baseCfgName = GetName();
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
 
-    aCfg->Write( baseCfgName + UserGridSizeXEntry, To_User_Unit( m_userUnits, m_UserGridSize.x ) );
-    aCfg->Write( baseCfgName + UserGridSizeYEntry, To_User_Unit( m_userUnits, m_UserGridSize.y ) );
-    aCfg->Write( baseCfgName + UserGridUnitsEntry, ( long )m_userUnits );
-    aCfg->Write( baseCfgName + DisplayPadFillEntry, m_DisplayOptions.m_DisplayPadFill );
-    aCfg->Write( baseCfgName + DisplayViaFillEntry, m_DisplayOptions.m_DisplayViaFill );
-    aCfg->Write( baseCfgName + DisplayPadNumberEntry, m_DisplayOptions.m_DisplayPadNum );
-    aCfg->Write( baseCfgName + DisplayModuleEdgeEntry, m_DisplayOptions.m_DisplayModEdgeFill );
-    aCfg->Write( baseCfgName + DisplayModuleTextEntry, m_DisplayOptions.m_DisplayModTextFill );
-    aCfg->Write( baseCfgName + FastGrid1Entry, ( long )m_FastGrid1 );
-    aCfg->Write( baseCfgName + FastGrid2Entry, ( long )m_FastGrid2 );
+    cfg->m_UserGrid.size_x = To_User_Unit( m_userUnits, m_UserGridSize.x );
+    cfg->m_UserGrid.size_y = To_User_Unit( m_userUnits, m_UserGridSize.y );
+    cfg->m_UserGrid.units = static_cast<int>( m_userUnits );
+
+    cfg->m_Display = m_DisplayOptions;
+    cfg->m_PolarCoords = m_PolarCoords;
+
+    cfg->m_FastGrid1 = m_FastGrid1;
+    cfg->m_FastGrid2 = m_FastGrid2;
+}
+
+
+PCBNEW_SETTINGS* PCB_BASE_FRAME::GetSettings()
+{
+    return Pgm().GetSettingsManager().GetAppSettings<PCBNEW_SETTINGS>();
 }
 
 
@@ -896,6 +884,7 @@ void PCB_BASE_FRAME::ActivateGalCanvas()
     auto settings = painter->GetSettings();
     auto displ_opts = GetDisplayOptions();
     settings->LoadDisplayOptions( displ_opts, ShowPageLimits() );
+    settings->LoadColors( ColorSettings() );
 
     canvas->GetView()->RecacheAllItems();
     canvas->SetEventDispatcher( m_toolDispatcher );
diff --git a/pcbnew/pcb_draw_panel_gal.cpp b/pcbnew/pcb_draw_panel_gal.cpp
index 803c984f49..d7c8bbe240 100644
--- a/pcbnew/pcb_draw_panel_gal.cpp
+++ b/pcbnew/pcb_draw_panel_gal.cpp
@@ -31,12 +31,13 @@
 #include <ratsnest_data.h>
 #include <connectivity/connectivity_data.h>
 
-#include <colors_design_settings.h>
 #include <class_board.h>
 #include <class_module.h>
 #include <class_track.h>
 #include <class_marker_pcb.h>
 #include <pcb_base_frame.h>
+#include <pgm_base.h>
+#include <settings/settings_manager.h>
 #include <confirm.h>
 
 #include <gal/graphics_abstraction_layer.h>
@@ -203,15 +204,23 @@ void PCB_DRAW_PANEL_GAL::SetWorksheet( KIGFX::WS_PROXY_VIEW_ITEM* aWorksheet )
 }
 
 
-void PCB_DRAW_PANEL_GAL::UseColorScheme( const COLORS_DESIGN_SETTINGS* aSettings )
+void PCB_DRAW_PANEL_GAL::UpdateColors()
 {
-    KIGFX::PCB_RENDER_SETTINGS* rs;
-    rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() );
-    rs->ImportLegacyColors( aSettings );
-    m_gal->SetGridColor( aSettings->GetLayerColor( LAYER_GRID ) );
-    m_gal->SetCursorColor( aSettings->GetItemColor( LAYER_CURSOR ) );
-}
+    COLOR_SETTINGS* cs = Pgm().GetSettingsManager().GetColorSettings();
 
+    auto frame = dynamic_cast<PCB_BASE_FRAME*>( GetParentEDAFrame() );
+
+    if( frame && frame->IsType( FRAME_FOOTPRINT_EDITOR ) )
+        cs->SetColorContext( COLOR_CONTEXT::FOOTPRINT );
+    else
+        cs->SetColorContext( COLOR_CONTEXT::PCB );
+
+    auto rs = static_cast<KIGFX::PCB_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() );
+    rs->LoadColors( cs );
+
+    m_gal->SetGridColor( cs->GetColor( LAYER_GRID ) );
+    m_gal->SetCursorColor( cs->GetColor( LAYER_CURSOR ) );
+}
 
 void PCB_DRAW_PANEL_GAL::SetHighContrastLayer( PCB_LAYER_ID aLayer )
 {
diff --git a/pcbnew/pcb_draw_panel_gal.h b/pcbnew/pcb_draw_panel_gal.h
index 0b930a3107..556b19fb99 100644
--- a/pcbnew/pcb_draw_panel_gal.h
+++ b/pcbnew/pcb_draw_panel_gal.h
@@ -35,7 +35,6 @@ namespace KIGFX
     class WS_PROXY_VIEW_ITEM;
     class RATSNEST_VIEWITEM;
 }
-class COLORS_DESIGN_SETTINGS;
 
 class PCB_DRAW_PANEL_GAL : public EDA_DRAW_PANEL_GAL
 {
@@ -61,12 +60,11 @@ public:
      */
     void SetWorksheet( KIGFX::WS_PROXY_VIEW_ITEM* aWorksheet );
 
+    // TODO(JE) Look at optimizing this out
     /**
-     * Function UseColorScheme
-     * Applies layer color settings.
-     * @param aSettings are the new settings.
+     * Updates the color settings in the painter and GAL
      */
-    void UseColorScheme( const COLORS_DESIGN_SETTINGS* aSettings );
+    void UpdateColors();
 
     ///> @copydoc EDA_DRAW_PANEL_GAL::SetHighContrastLayer()
     virtual void SetHighContrastLayer( int aLayer ) override
diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp
index 9648d43ca1..fb7bd71842 100644
--- a/pcbnew/pcb_edit_frame.cpp
+++ b/pcbnew/pcb_edit_frame.cpp
@@ -32,9 +32,9 @@
 #include <pcbnew.h>
 #include <pcbnew_id.h>
 #include <drc/drc.h>
+#include <pcbnew_settings.h>
 #include <layer_widget.h>
 #include <pcb_layer_widget.h>
-#include <config_params.h>
 #include <footprint_edit_frame.h>
 #include <dialog_plot.h>
 #include <dialog_edit_footprint_for_BoardEditor.h>
@@ -54,6 +54,7 @@
 #include <kicad_string.h>
 #include <pcb_draw_panel_gal.h>
 #include <functional>
+#include <settings/settings_manager.h>
 #include <tool/tool_manager.h>
 #include <tool/tool_dispatcher.h>
 #include <tool/action_toolbar.h>
@@ -94,16 +95,6 @@
 
 using namespace std::placeholders;
 
-///@{
-/// \ingroup config
-
-static const wxString PlotLineWidthEntry =      "PlotLineWidth_mm";
-static const wxString ShowMicrowaveEntry =      "ShowMicrowaveTools";
-static const wxString ShowLayerManagerEntry =   "ShowLayerManagerTools";
-static const wxString ShowPageLimitsEntry =     "ShowPageLimits";
-
-///@}
-
 
 BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
     EVT_SOCKET( ID_EDA_SOCKET_EVENT_SERV, PCB_EDIT_FRAME::OnSockRequestServer )
@@ -562,10 +553,8 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& aEvent )
 void PCB_EDIT_FRAME::ActivateGalCanvas()
 {
     PCB_BASE_EDIT_FRAME::ActivateGalCanvas();
-    COLORS_DESIGN_SETTINGS& cds = Settings().Colors();
-
-    GetCanvas()->GetGAL()->SetGridColor( cds.GetLayerColor( LAYER_GRID ) );
-    GetCanvas()->GetView()->GetPainter()->GetSettings()->ImportLegacyColors( &cds );
+    ColorSettings()->SetColorContext( COLOR_CONTEXT::PCB );
+    GetCanvas()->UpdateColors();
     GetCanvas()->Refresh();
 }
 
@@ -600,53 +589,59 @@ void PCB_EDIT_FRAME::DoShowBoardSetupDialog( const wxString& aInitialPage,
 }
 
 
-void PCB_EDIT_FRAME::LoadSettings( wxConfigBase* aCfg )
+void PCB_EDIT_FRAME::LoadSettings( APP_SETTINGS_BASE* aCfg )
 {
     PCB_BASE_FRAME::LoadSettings( aCfg );
 
-    wxConfigLoadSetups( aCfg, GetConfigurationSettings() );
+    // TODO(JE) remove once color themes exist
+    COLOR_SETTINGS* cs = ColorSettings();
+    cs->SetColorContext( COLOR_CONTEXT::PCB );
+    cs->Load();
 
-    m_configSettings.Load( aCfg );
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
 
-    double dtmp;
-    aCfg->Read( PlotLineWidthEntry, &dtmp, 0.1 ); // stored in mm
-    dtmp = std::max( 0.01, std::min( dtmp, 5.0 ) );
-
-    g_DrawDefaultLineThickness = Millimeter2iu( dtmp );
-
-    aCfg->Read( ShowMicrowaveEntry, &m_show_microwave_tools );
-    aCfg->Read( ShowLayerManagerEntry, &m_show_layer_manager_tools );
-
-    aCfg->Read( ShowPageLimitsEntry, &m_showPageLimits );
+    m_rotationAngle            = cfg->m_RotationAngle;
+    g_DrawDefaultLineThickness = Millimeter2iu( cfg->m_PlotLineWidth );
+    m_show_microwave_tools     = cfg->m_AuiPanels.show_microwave_tools;
+    m_show_layer_manager_tools = cfg->m_AuiPanels.show_layer_manager;
+    m_showPageLimits           = cfg->m_ShowPageLimits;
 }
 
 
-void PCB_EDIT_FRAME::SaveSettings( wxConfigBase* aCfg )
+void PCB_EDIT_FRAME::SaveSettings( APP_SETTINGS_BASE* aCfg )
 {
-    m_configSettings.Save( aCfg );
-
     PCB_BASE_FRAME::SaveSettings( aCfg );
 
-    wxConfigSaveSetups( aCfg, GetConfigurationSettings() );
+    // TODO(JE) remove once color themes exist
+    COLOR_SETTINGS* cs = ColorSettings();
+    cs->SetColorContext( COLOR_CONTEXT::PCB );
+    cs->Store();
 
-    // This value is stored in mm )
-    aCfg->Write( PlotLineWidthEntry, MM_PER_IU * g_DrawDefaultLineThickness );
-    aCfg->Write( ShowMicrowaveEntry, (long) m_show_microwave_tools );
-    aCfg->Write( ShowLayerManagerEntry, (long)m_show_layer_manager_tools );
-    aCfg->Write( ShowPageLimitsEntry, m_showPageLimits );
+    // Ensure pcbnew color settings get flushed to disk before context is changed
+    Pgm().GetSettingsManager().SaveColorSettings( cs, "board" );
+
+    auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aCfg );
+    wxASSERT( cfg );
+
+    cfg->m_RotationAngle                  = m_rotationAngle;
+    cfg->m_PlotLineWidth                  = Iu2Millimeter( g_DrawDefaultLineThickness );
+    cfg->m_AuiPanels.show_microwave_tools = m_show_microwave_tools;
+    cfg->m_AuiPanels.show_layer_manager   = m_show_layer_manager_tools;
+    cfg->m_ShowPageLimits                 = m_showPageLimits;
 }
 
 
 COLOR4D PCB_EDIT_FRAME::GetGridColor()
 {
-    return Settings().Colors().GetItemColor( LAYER_GRID );
+    return ColorSettings()->GetColor( LAYER_GRID );
 }
 
 
 void PCB_EDIT_FRAME::SetGridColor( COLOR4D aColor )
 {
 
-    Settings().Colors().SetItemColor( LAYER_GRID, aColor );
+    ColorSettings()->SetColor( LAYER_GRID, aColor );
     GetCanvas()->GetGAL()->SetGridColor( aColor );
 }
 
diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h
index 8629005106..e5054a9107 100644
--- a/pcbnew/pcb_edit_frame.h
+++ b/pcbnew/pcb_edit_frame.h
@@ -102,7 +102,6 @@ class PCB_EDIT_FRAME : public PCB_BASE_EDIT_FRAME
     ACTION_TOOLBAR*         m_microWaveToolBar;
 
 protected:
-    std::vector<PARAM_CFG*> m_configParams;           // List of Pcbnew configuration settings.
     std::vector<PARAM_CFG*> m_projectFileParams;
 
     wxString                m_lastPath[ LAST_PATH_SIZE ];
@@ -371,17 +370,15 @@ public:
 #if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
 
     /**
-     * Function SetActionPluginSettings
      * Set a set of plugins that have visible buttons on toolbar
      * Plugins are identified by their module path
      */
-    void SetActionPluginSettings( const std::vector< std::pair<wxString, wxString> >& aPluginsWithButtons );
+    void SetActionPluginSettings( const std::vector<wxString>& aPluginsWithButtons );
 
     /**
-     * Function GetActionPluginSettings
      * Get a set of plugins that have visible buttons on toolbar
      */
-    std::vector< std::pair<wxString, wxString> > GetActionPluginSettings();
+    std::vector<wxString> GetActionPluginSettings();
 
     /**
      * Function GetActionPluginButtonVisible
@@ -427,28 +424,9 @@ public:
      */
     bool LoadProjectSettings();
 
-    /**
-     * Function GetConfigurationSettings
-     * returns the Pcbnew applications settings list.
-     *
-     * This replaces the old statically defined list that had the project
-     * file settings and the application settings mixed together.  This
-     * was confusing and caused some settings to get saved and loaded
-     * incorrectly.  Currently, only the settings that are needed at start
-     * up by the main window are defined here.  There are other locally used
-     * settings that are scattered throughout the Pcbnew source code.  If you need
-     * to define a configuration setting that needs to be loaded at run time,
-     * this is the place to define it.
-     *
-     * @return - Reference to the list of applications settings.
-     */
-    std::vector<PARAM_CFG*>& GetConfigurationSettings();
+    void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
 
-    void LoadSettings( wxConfigBase* aCfg ) override;
-
-    void SaveSettings( wxConfigBase* aCfg ) override;
-
-    wxConfigBase* GetSettings() { return config(); };
+    void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
 
     /**
      * Get the last path for a particular type.
diff --git a/pcbnew/pcb_general_settings.h b/pcbnew/pcb_general_settings.h
deleted file mode 100644
index 65b1febacf..0000000000
--- a/pcbnew/pcb_general_settings.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * This program source code file is part of KICAD, a free EDA CAD application.
- *
- * Copyright (C) 2012-2019 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 2
- * 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, you may find one here:
- * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- * or you may search the http://www.gnu.org website for the version 2 license,
- * or you may write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-#ifndef PCBNEW_GENERAL_SETTINGS_H
-#define PCBNEW_GENERAL_SETTINGS_H
-
-#include <colors_design_settings.h>
-#include <vector>
-
-class wxConfigBase;
-class wxString;
-
-enum MAGNETIC_OPTIONS
-{
-    NO_EFFECT,
-    CAPTURE_CURSOR_IN_TRACK_TOOL,
-    CAPTURE_ALWAYS
-};
-
-class PCB_GENERAL_SETTINGS : public SETTINGS
-{
-public:
-    PCB_GENERAL_SETTINGS( FRAME_T aFrameType );
-
-    void Load( wxConfigBase* aCfg ) override;
-    void Save( wxConfigBase* aCfg ) override;
-
-    COLORS_DESIGN_SETTINGS& Colors() { return m_colorsSettings; }
-
-    bool m_Use45DegreeGraphicSegments;   // True to constraint graphic lines to horizontal,
-                                         // vertical and 45ยบ
-    bool m_FlipLeftRight;                // True: Flip footprints across Y axis
-                                         // False: Flip footprints across X axis
-
-    MAGNETIC_OPTIONS m_MagneticPads;
-    MAGNETIC_OPTIONS m_MagneticTracks;
-    bool             m_MagneticGraphics;
-
-#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
-    std::vector< std::pair<wxString, wxString> > m_pluginSettings;  // Settings for action plugins
-#endif
-
-protected:
-    const FRAME_T           m_frameType;
-    COLORS_DESIGN_SETTINGS  m_colorsSettings;
-};
-
-#endif  // PCBNEW_GENERAL_SETTINGS_H
diff --git a/pcbnew/pcb_layer_box_selector.cpp b/pcbnew/pcb_layer_box_selector.cpp
index 1103594045..a9e91bdfc6 100644
--- a/pcbnew/pcb_layer_box_selector.cpp
+++ b/pcbnew/pcb_layer_box_selector.cpp
@@ -33,6 +33,7 @@
 #include <pcb_edit_frame.h>
 #include <board_design_settings.h>
 #include <layers_id_colors_and_visibility.h>
+#include <settings/color_settings.h>
 
 #include <class_board.h>
 #include <pcb_layer_box_selector.h>
@@ -141,7 +142,7 @@ COLOR4D PCB_LAYER_BOX_SELECTOR::GetLayerColor( LAYER_NUM aLayer ) const
 {
     wxASSERT( m_boardFrame );
 
-    return m_boardFrame->Settings().Colors().GetLayerColor( aLayer );
+    return m_boardFrame->ColorSettings()->GetColor( aLayer );
 }
 
 
diff --git a/pcbnew/pcb_layer_widget.cpp b/pcbnew/pcb_layer_widget.cpp
index a9023a7619..5df16ab765 100644
--- a/pcbnew/pcb_layer_widget.cpp
+++ b/pcbnew/pcb_layer_widget.cpp
@@ -24,29 +24,30 @@
  */
 
 
-#include <fctsys.h>
-#include <pgm_base.h>
-#include <pcb_draw_panel_gal.h>
-#include <view/view.h>
-#include <painter.h>
-#include <confirm.h>
-#include <pcb_edit_frame.h>
-#include <pcb_display_options.h>
-#include <tool/tool_manager.h>
-#include <layer_widget.h>
+#include <class_board.h>
 #include <class_text_mod.h>
-#include <widgets/indicator_icon.h>
+#include <collectors.h>
+#include <confirm.h>
+#include <fctsys.h>
+#include <gal/graphics_abstraction_layer.h>
+#include <layer_widget.h>
 #include <macros.h>
 #include <menus_helpers.h>
-#include <gal/graphics_abstraction_layer.h>
+#include <painter.h>
+#include <pcb_display_options.h>
+#include <pcb_draw_panel_gal.h>
+#include <pcb_edit_frame.h>
+#include <pcb_layer_widget.h>
 #include <pcb_painter.h>
 #include <pcb_view.h>
-#include <class_board.h>
-#include <pcb_layer_widget.h>
 #include <pcbnew.h>
-#include <collectors.h>
 #include <pcbnew_id.h>
-#include <gal/graphics_abstraction_layer.h>
+#include <pcbnew_settings.h>
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <tool/tool_manager.h>
+#include <view/view.h>
+#include <widgets/indicator_icon.h>
 
 
 /// This is a read only template that is copied and modified before adding to LAYER_WIDGET
@@ -126,7 +127,9 @@ PCB_LAYER_WIDGET::PCB_LAYER_WIDGET( PCB_BASE_FRAME* aParent, wxWindow* aFocusOwn
 
 COLOR4D PCB_LAYER_WIDGET::getBackgroundLayerColor()
 {
-    return myframe->Settings().Colors().GetLayerColor( LAYER_PCB_BACKGROUND );
+    myframe->ColorSettings()->SetColorContext( m_fp_editor_mode ?
+                                               COLOR_CONTEXT::FOOTPRINT : COLOR_CONTEXT::PCB );
+    return myframe->ColorSettings()->GetColor( LAYER_PCB_BACKGROUND );
 }
 
 
@@ -375,6 +378,9 @@ void PCB_LAYER_WIDGET::ReFillRender()
     BOARD* board = myframe->GetBoard();
     auto settings = board->GetDesignSettings();
 
+    myframe->ColorSettings()->SetColorContext( m_fp_editor_mode ?
+                                               COLOR_CONTEXT::FOOTPRINT : COLOR_CONTEXT::PCB );
+
     ClearRenderRows();
 
     // Add "Items" tab rows to LAYER_WIDGET, after setting color and checkbox state.
@@ -402,9 +408,9 @@ void PCB_LAYER_WIDGET::ReFillRender()
             if( renderRow.color != COLOR4D::UNSPECIFIED )       // does this row show a color?
             {
                 // this window frame must have an established BOARD, i.e. after SetBoard()
-                renderRow.color = myframe->Settings().Colors().GetItemColor(
+                renderRow.color = myframe->ColorSettings()->GetColor(
                         static_cast<GAL_LAYER_ID>( renderRow.id ) );
-                renderRow.defaultColor = myframe->Settings().Colors().GetDefaultItemColor(
+                renderRow.defaultColor = myframe->ColorSettings()->GetDefaultColor(
                         static_cast<GAL_LAYER_ID>( renderRow.id ) );
             }
 
@@ -485,6 +491,9 @@ void PCB_LAYER_WIDGET::ReFill()
     BOARD*  brd = myframe->GetBoard();
     LSET    enabled = brd->GetEnabledLayers();
 
+    myframe->ColorSettings()->SetColorContext( m_fp_editor_mode ?
+                                               COLOR_CONTEXT::FOOTPRINT : COLOR_CONTEXT::PCB );
+
     ClearLayerRows();
 
     wxString dsc;
@@ -510,8 +519,8 @@ void PCB_LAYER_WIDGET::ReFill()
         }
 
         AppendLayerRow( LAYER_WIDGET::ROW( brd->GetLayerName( layer ), layer,
-                myframe->Settings().Colors().GetLayerColor( layer ), dsc, true, true,
-                myframe->Settings().Colors().GetDefaultLayerColor( layer ) ) );
+                myframe->ColorSettings()->GetColor( layer ), dsc, true, true,
+                myframe->ColorSettings()->GetDefaultColor( layer ) ) );
 
         if( m_fp_editor_mode && LSET::ForbiddenFootprintLayers().test( layer ) )
         {
@@ -558,9 +567,9 @@ void PCB_LAYER_WIDGET::ReFill()
             continue;
 
         AppendLayerRow( LAYER_WIDGET::ROW( brd->GetLayerName( layer ), layer,
-                myframe->Settings().Colors().GetLayerColor( layer ),
+                myframe->ColorSettings()->GetColor( layer ),
                 wxGetTranslation( non_cu_seq[i].tooltip ), true, true,
-                myframe->Settings().Colors().GetDefaultLayerColor( layer ) ) );
+                myframe->ColorSettings()->GetDefaultColor( layer ) ) );
 
         if( m_fp_editor_mode && LSET::ForbiddenFootprintLayers().test( layer ) )
         {
@@ -575,10 +584,12 @@ void PCB_LAYER_WIDGET::ReFill()
 
 void PCB_LAYER_WIDGET::OnLayerColorChange( int aLayer, COLOR4D aColor )
 {
-    myframe->Settings().Colors().SetLayerColor( aLayer, aColor );
+    myframe->ColorSettings()->SetColorContext( m_fp_editor_mode ?
+                                               COLOR_CONTEXT::FOOTPRINT : COLOR_CONTEXT::PCB );
+    myframe->ColorSettings()->SetColor( aLayer, aColor );
+    myframe->GetCanvas()->UpdateColors();
 
     KIGFX::VIEW* view = myframe->GetCanvas()->GetView();
-    view->GetPainter()->GetSettings()->ImportLegacyColors( &myframe->Settings().Colors() );
     view->UpdateLayerColor( aLayer );
     view->UpdateLayerColor( GetNetnameLayer( aLayer ) );
 
@@ -661,13 +672,12 @@ void PCB_LAYER_WIDGET::OnRenderColorChange( int aId, COLOR4D aColor )
 {
     wxASSERT( aId > GAL_LAYER_ID_START && aId < GAL_LAYER_ID_END );
 
-    myframe->Settings().Colors().SetItemColor( static_cast<GAL_LAYER_ID>( aId ), aColor );
-
-    if( aId == LAYER_GRID )
-        myframe->GetCanvas()->GetGAL()->SetGridColor( aColor );
+    myframe->ColorSettings()->SetColorContext( m_fp_editor_mode ?
+                                               COLOR_CONTEXT::FOOTPRINT : COLOR_CONTEXT::PCB );
+    myframe->ColorSettings()->SetColor( aId, aColor );
+    myframe->GetCanvas()->UpdateColors();
 
     KIGFX::VIEW* view = myframe->GetCanvas()->GetView();
-    view->GetPainter()->GetSettings()->ImportLegacyColors( &myframe->Settings().Colors() );
     view->MarkTargetDirty( KIGFX::TARGET_NONCACHED );   // useful to update rastnest
     view->UpdateLayerColor( aId );
 
diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp
index 39c3b90347..9db48e8d4d 100644
--- a/pcbnew/pcb_painter.cpp
+++ b/pcbnew/pcb_painter.cpp
@@ -30,7 +30,6 @@
 #include <class_drawsegment.h>
 #include <class_zone.h>
 #include <class_pcb_text.h>
-#include <colors_design_settings.h>
 #include <class_marker_pcb.h>
 #include <class_dimension.h>
 #include <class_pcb_target.h>
@@ -39,6 +38,7 @@
 #include <layers_id_colors_and_visibility.h>
 #include <pcb_painter.h>
 #include <pcb_display_options.h>
+#include <settings/color_settings.h>
 
 #include <convert_basic_shapes_to_polygon.h>
 #include <gal/graphics_abstraction_layer.h>
@@ -69,19 +69,18 @@ PCB_RENDER_SETTINGS::PCB_RENDER_SETTINGS()
         m_sketchMode[i] = false;
     }
 
-    COLORS_DESIGN_SETTINGS dummyCds( FRAME_PCB_EDITOR );
-    ImportLegacyColors( &dummyCds );
-
     update();
 }
 
 
-void PCB_RENDER_SETTINGS::ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSettings )
+void PCB_RENDER_SETTINGS::LoadColors( const COLOR_SETTINGS* aSettings )
 {
+    SetBackgroundColor( aSettings->GetColor( LAYER_PCB_BACKGROUND ) );
+
     // Init board layers colors:
     for( int i = 0; i < PCB_LAYER_ID_COUNT; i++ )
     {
-        m_layerColors[i] = aSettings->GetLayerColor( i );
+        m_layerColors[i] = aSettings->GetColor( i );
 
         // Guard: if the alpah channel is too small, the layer is not visible.
         // clamp it to 0.2
@@ -91,11 +90,11 @@ void PCB_RENDER_SETTINGS::ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSet
 
     // Init specific graphic layers colors:
     for( int i = GAL_LAYER_ID_START; i < GAL_LAYER_ID_END; i++ )
-        m_layerColors[i] = aSettings->GetItemColor( i );
+        m_layerColors[i] = aSettings->GetColor( i );
 
     // Default colors for specific layers (not really board layers).
     m_layerColors[LAYER_VIAS_HOLES]         = COLOR4D( 0.5, 0.4, 0.0, 0.8 );
-    m_layerColors[LAYER_PADS_PLATEDHOLES]   = aSettings->GetItemColor( LAYER_PCB_BACKGROUND );
+    m_layerColors[LAYER_PADS_PLATEDHOLES]   = aSettings->GetColor( LAYER_PCB_BACKGROUND );
     m_layerColors[LAYER_VIAS_NETNAMES]      = COLOR4D( 0.2, 0.2, 0.2, 0.9 );
     m_layerColors[LAYER_PADS_NETNAMES]      = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
     m_layerColors[LAYER_PAD_FR_NETNAMES]    = COLOR4D( 1.0, 1.0, 1.0, 0.9 );
diff --git a/pcbnew/pcb_painter.h b/pcbnew/pcb_painter.h
index e822ac411d..067acccb30 100644
--- a/pcbnew/pcb_painter.h
+++ b/pcbnew/pcb_painter.h
@@ -89,9 +89,6 @@ public:
 
     PCB_RENDER_SETTINGS();
 
-    /// @copydoc RENDER_SETTINGS::ImportLegacyColors()
-    void ImportLegacyColors( const COLORS_DESIGN_SETTINGS* aSettings ) override;
-
     /**
      * Function LoadDisplayOptions
      * Loads settings related to display options (high-contrast mode, full or outline modes
@@ -100,6 +97,8 @@ public:
      */
     void LoadDisplayOptions( const PCB_DISPLAY_OPTIONS& aOptions, bool aShowPageLimits );
 
+    virtual void LoadColors( const COLOR_SETTINGS* aSettings ) override;
+
     /// @copydoc RENDER_SETTINGS::GetColor()
     virtual const COLOR4D& GetColor( const VIEW_ITEM* aItem, int aLayer ) const override;
 
diff --git a/pcbnew/pcb_plot_params.cpp b/pcbnew/pcb_plot_params.cpp
index 76f30109c2..0da18ac71c 100644
--- a/pcbnew/pcb_plot_params.cpp
+++ b/pcbnew/pcb_plot_params.cpp
@@ -21,14 +21,17 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <pcb_plot_params_parser.h>
-#include <pcb_plot_params.h>
-#include <layers_id_colors_and_visibility.h>
-#include <plotter.h>
-#include <macros.h>
-#include <convert_to_biu.h>
 #include <board_design_settings.h>
-#include <math/util.h>      // for KiROUND
+#include <convert_to_biu.h>
+#include <layers_id_colors_and_visibility.h>
+#include <macros.h>
+#include <math/util.h> // for KiROUND
+#include <pcb_plot_params.h>
+#include <pcb_plot_params_parser.h>
+#include <pgm_base.h>
+#include <plotter.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
 
 
 #define PLOT_LINEWIDTH_MIN        ( 0.02 * IU_PER_MM )  // min value for default line thickness
@@ -134,6 +137,9 @@ PCB_PLOT_PARAMS::PCB_PLOT_PARAMS()
     // This parameter controls if the NPTH pads will be plotted or not
     // it is a "local" parameter
     m_skipNPTH_Pads              = false;
+
+    // TODO(JE) Is it an issue for this to be tied to Pgm()?
+    m_colors = Pgm().GetSettingsManager().GetColorSettings();
 }
 
 void PCB_PLOT_PARAMS::SetGerberPrecision( int aPrecision )
diff --git a/pcbnew/pcb_plot_params.h b/pcbnew/pcb_plot_params.h
index 5fa4bce089..b98396c387 100644
--- a/pcbnew/pcb_plot_params.h
+++ b/pcbnew/pcb_plot_params.h
@@ -28,6 +28,7 @@
 #include <plotter.h>
 #include <layers_id_colors_and_visibility.h>
 
+class COLOR_SETTINGS;
 class PCB_PLOT_PARAMS_PARSER;
 
 /**
@@ -171,6 +172,9 @@ private:
                                         ///< However, it is in mm in hpgl files.
     COLOR4D     m_color;                ///< Color for plotting the current layer. Provided, but not really used
 
+    /// Pointer to active color settings to be used for plotting
+    COLOR_SETTINGS* m_colors;
+
 public:
     PCB_PLOT_PARAMS();
 
@@ -192,6 +196,10 @@ public:
     void        SetColor( COLOR4D aVal ) { m_color = aVal; }
     COLOR4D     GetColor() const { return m_color; }
 
+    void SetColorSettings( COLOR_SETTINGS* aSettings ) { m_colors = aSettings; }
+
+    COLOR_SETTINGS* ColorSettings() const { return m_colors; }
+
     void SetTextMode( PLOT_TEXT_MODE aVal )
     {
         m_textMode = aVal;
diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp
index 8eee786fa2..b5484b8c2c 100644
--- a/pcbnew/pcbnew.cpp
+++ b/pcbnew/pcbnew.cpp
@@ -44,6 +44,8 @@
 #include <wx/snglinst.h>
 #include <gestfich.h>
 #include <pcbnew.h>
+#include <pcbnew_settings.h>
+#include <settings/settings_manager.h>
 #include <class_board.h>
 #include <class_draw_panel_gal.h>
 #include <fp_lib_table.h>
@@ -321,6 +323,8 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
 {
     // This is process-level-initialization, not project-level-initialization of the DSO.
     // Do nothing in here pertinent to a project!
+    InitSettings( new PCBNEW_SETTINGS );
+    aProgram->GetSettingsManager().RegisterSettings( KifaceSettings() );
 
     start_common( aCtlBits );
 
diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp
index 784c769ad9..2ed296bb09 100644
--- a/pcbnew/pcbnew_config.cpp
+++ b/pcbnew/pcbnew_config.cpp
@@ -145,53 +145,3 @@ std::vector<PARAM_CFG*>& PCB_EDIT_FRAME::GetProjectFileParameters()
 
     return m_projectFileParams;
 }
-
-
-std::vector<PARAM_CFG*>& PCB_EDIT_FRAME::GetConfigurationSettings()
-{
-    PCB_DISPLAY_OPTIONS& displ_opts = m_DisplayOptions;
-
-    if( m_configParams.empty() )
-    {
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "DisplayPolarCoords" ),
-                                                        &m_PolarCoords, false ) );
-        // Display options and modes:
-        m_configParams.push_back( new PARAM_CFG_INT( true, wxT( "ShowNetNamesMode" ),
-                                                     &displ_opts.m_DisplayNetNamesMode, 3, 0, 3 ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "DisplayTrackFilled" ),
-                                                      &displ_opts.m_DisplayPcbTrackFill, true ) );
-        m_configParams.push_back( new PARAM_CFG_INT( true, wxT( "TrackDisplayClearance" ),
-                                                     (int*) &displ_opts.m_ShowTrackClearanceMode,
-                                                     PCB_DISPLAY_OPTIONS::SHOW_CLEARANCE_NEW_TRACKS_AND_VIA_AREAS ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "PadFill" ),
-                                                      &displ_opts.m_DisplayPadFill, true ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "ViaFill" ),
-                                                      &displ_opts.m_DisplayViaFill, true ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "PadAffG" ),
-                                                      &displ_opts.m_DisplayPadIsol, true ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "PadSNum" ),
-                                                      &displ_opts.m_DisplayPadNum, true ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "ModAffC" ),
-                                                     &displ_opts.m_DisplayModEdgeFill, FILLED ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "ModAffT" ),
-                                                     &displ_opts.m_DisplayModTextFill, FILLED ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "PcbAffT" ),
-                                                     &displ_opts.m_DisplayDrawItemsFill, FILLED ) );
-        m_configParams.push_back( new PARAM_CFG_INT( true, wxT( "PcbShowZonesMode" ),
-                                                     &displ_opts.m_DisplayZonesMode, 0, 0, 2 ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "CurvedRatsnestLines" ),
-                                                      &displ_opts.m_DisplayRatsnestLinesCurved, false ) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "ShowRatsnestLines" ),
-                                                      &displ_opts.m_ShowGlobalRatsnest, true) );
-        m_configParams.push_back( new PARAM_CFG_BOOL( true, wxT( "ShowRatsnestModuleLines" ),
-                                                      &displ_opts.m_ShowModuleRatsnest, true) );
-
-        // Miscellaneous:
-        m_configParams.push_back( new PARAM_CFG_INT( true, wxT( "RotationAngle" ),
-                                                     &m_rotationAngle, 900, 1, 900 ) );
-        m_configParams.push_back( new PARAM_CFG_INT( true, wxT( "MaxLnkS" ),
-                                                     &displ_opts.m_MaxLinksShowed, 3, 0, 15 ) );
-    }
-
-    return m_configParams;
-}
diff --git a/pcbnew/pcbnew_printout.cpp b/pcbnew/pcbnew_printout.cpp
index a318195046..65ad1416e7 100644
--- a/pcbnew/pcbnew_printout.cpp
+++ b/pcbnew/pcbnew_printout.cpp
@@ -29,6 +29,7 @@
 #include <class_board.h>
 #include <math/util.h>      // for KiROUND
 #include <pcb_painter.h>
+#include <pcbnew_settings.h>
 #include <view/view.h>
 #include <pcbplot.h>
 
@@ -41,19 +42,27 @@ PCBNEW_PRINTOUT_SETTINGS::PCBNEW_PRINTOUT_SETTINGS( const PAGE_INFO& aPageInfo )
 }
 
 
-void PCBNEW_PRINTOUT_SETTINGS::Load( wxConfigBase* aConfig )
+void PCBNEW_PRINTOUT_SETTINGS::Load( APP_SETTINGS_BASE* aConfig )
 {
     BOARD_PRINTOUT_SETTINGS::Load( aConfig );
-    aConfig->Read( OPTKEY_PRINT_PADS_DRILL, (int*) &m_drillMarks, FULL_DRILL_SHAPE );
-    aConfig->Read( OPTKEY_PRINT_PAGE_PER_LAYER, (int*) &m_pagination, ALL_LAYERS );
+
+    if( auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aConfig ) )
+    {
+        m_drillMarks = static_cast<DRILL_MARK_SHAPE_T>( cfg->m_Plot.pads_drill_mode );
+        m_pagination = static_cast<PAGINATION_T>( cfg->m_Plot.one_page_per_layer );
+    }
 }
 
 
-void PCBNEW_PRINTOUT_SETTINGS::Save( wxConfigBase* aConfig )
+void PCBNEW_PRINTOUT_SETTINGS::Save( APP_SETTINGS_BASE* aConfig )
 {
     BOARD_PRINTOUT_SETTINGS::Save( aConfig );
-    aConfig->Write( OPTKEY_PRINT_PADS_DRILL, (int) m_drillMarks );
-    aConfig->Write( OPTKEY_PRINT_PAGE_PER_LAYER, (int) m_pagination );
+
+    if( auto cfg = dynamic_cast<PCBNEW_SETTINGS*>( aConfig ) )
+    {
+        cfg->m_Plot.pads_drill_mode    = m_drillMarks;
+        cfg->m_Plot.one_page_per_layer = m_pagination;
+    }
 }
 
 
diff --git a/pcbnew/pcbnew_printout.h b/pcbnew/pcbnew_printout.h
index 8881735a50..bf15fd9807 100644
--- a/pcbnew/pcbnew_printout.h
+++ b/pcbnew/pcbnew_printout.h
@@ -42,8 +42,8 @@ struct PCBNEW_PRINTOUT_SETTINGS : BOARD_PRINTOUT_SETTINGS
 
     bool m_noEdgeLayer;         ///< Disable board outline on each page
 
-    void Load( wxConfigBase* aConfig ) override;
-    void Save( wxConfigBase* aConfig ) override;
+    void Load( APP_SETTINGS_BASE* aConfig ) override;
+    void Save( APP_SETTINGS_BASE* aConfig ) override;
 };
 
 
diff --git a/pcbnew/pcbnew_settings.cpp b/pcbnew/pcbnew_settings.cpp
new file mode 100644
index 0000000000..37070c7a0d
--- /dev/null
+++ b/pcbnew/pcbnew_settings.cpp
@@ -0,0 +1,630 @@
+/*
+* This program source code file is part of KiCad, a free EDA CAD application.
+*
+* Copyright (C) 2020 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 2
+* 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, you may find one here:
+* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+* or you may search the http://www.gnu.org website for the version 2 license,
+* or you may write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
+
+#include <common.h>
+#include <footprint_editor_settings.h>
+#include <layers_id_colors_and_visibility.h>
+#include <pcbnew_settings.h>
+#include <pgm_base.h>
+#include <router/pns_routing_settings.h>
+#include <settings/common_settings.h>
+#include <settings/nested_settings.h>
+#include <settings/parameters.h>
+#include <settings/settings_manager.h>
+#include <wx/config.h>
+#include <wx/tokenzr.h>
+#include <zones.h>
+
+#include "../3d-viewer/3d_viewer/3d_viewer_settings.h"
+
+
+///! Update the schema version whenever a migration is required
+const int pcbnewSchemaVersion = 0;
+
+
+PCBNEW_SETTINGS::PCBNEW_SETTINGS() : APP_SETTINGS_BASE( "pcbnew", pcbnewSchemaVersion ),
+        m_Use45DegreeGraphicSegments( false ),
+        m_FlipLeftRight( false ),
+        m_MagneticPads( MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ),
+        m_MagneticTracks( MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ),
+        m_MagneticGraphics( true ),
+        m_PnsSettings( nullptr )
+{
+    m_params.emplace_back( new PARAM<bool>( "aui.show_layer_manager",
+            &m_AuiPanels.show_layer_manager, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "aui.show_microwave_tools",
+            &m_AuiPanels.show_microwave_tools, false ) );
+
+    m_params.emplace_back( new PARAM<int>( "footprint_chooser.width",
+            &m_FootprintChooser.width, -1 ) );
+
+    m_params.emplace_back( new PARAM<int>( "footprint_chooser.height",
+            &m_FootprintChooser.height, -1 ) );
+
+    m_params.emplace_back( new PARAM<int>( "footprint_chooser.sash_h",
+            &m_FootprintChooser.sash_h, -1 ) );
+
+    m_params.emplace_back( new PARAM<int>( "footprint_chooser.sash_v",
+            &m_FootprintChooser.sash_v, -1 ) );
+
+    m_params.emplace_back( new PARAM<int>( "grid.fast_grid_1", &m_FastGrid1, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "grid.fast_grid_2", &m_FastGrid2, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "window.auto_zoom", &m_Window.auto_zoom, true ) );
+
+    m_params.emplace_back( new PARAM<double>( "window.zoom", &m_Window.zoom, 10.0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "editing.flip_left_right", &m_FlipLeftRight, true ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "editing.magnetic_graphics", &m_MagneticGraphics, true ) );
+
+    m_params.emplace_back( new PARAM<int>( "editing.magnetic_pads",
+            reinterpret_cast<int*>( &m_MagneticPads ),
+            static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ) ) );
+
+    m_params.emplace_back( new PARAM<int>( "editing.magnetic_tracks",
+            reinterpret_cast<int*>( &m_MagneticTracks ),
+            static_cast<int>( MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ) ) );
+
+    m_params.emplace_back( new PARAM<bool>( "editing.polar_coords", &m_PolarCoords, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "editing.use_45_degree_graphic_segments",
+            &m_Use45DegreeGraphicSegments, false ) );
+
+    m_params.emplace_back( new PARAM<int>( "grid.user.units",
+            &m_UserGrid.units, static_cast<int>( EDA_UNITS::INCHES ) ) );
+
+    m_params.emplace_back( new PARAM<double>( "grid.user.size_x", &m_UserGrid.size_x, 0.01 ) );
+
+    m_params.emplace_back( new PARAM<double>( "grid.user.size_y", &m_UserGrid.size_y, 0.01 ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "pcb_display.graphic_items_fill", &m_Display.m_DisplayDrawItemsFill, true ) );
+
+    m_params.emplace_back( new PARAM<int>(
+            "pcb_display.max_links_shown", &m_Display.m_MaxLinksShowed, 3, 0, 15 ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "pcb_display.footprint_edge_fill", &m_Display.m_DisplayModEdgeFill, true ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "pcb_display.footprint_text_fill", &m_Display.m_DisplayModTextFill, true ) );
+
+    m_params.emplace_back( new PARAM<int>(
+            "pcb_display.net_names_mode", &m_Display.m_DisplayNetNamesMode, 3, 0, 3 ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "pcb_display.pad_clearance", &m_Display.m_DisplayPadIsol, true ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "pcb_display.pad_fill", &m_Display.m_DisplayPadFill, true ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "pcb_display.pad_numbers", &m_Display.m_DisplayPadNum, true ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "pcb_display.ratsnest_global", &m_Display.m_ShowGlobalRatsnest, true ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "pcb_display.ratsnest_footprint", &m_Display.m_ShowModuleRatsnest, true ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "pcb_display.ratsnest_curved", &m_Display.m_DisplayRatsnestLinesCurved, false ) );
+
+    m_params.emplace_back( new PARAM<int>(
+            "pcb_display.rotation_angle", &m_RotationAngle, 900, 1, 900 ) );
+
+    m_params.emplace_back( new PARAM<int>( "pcb_display.track_clearance_mode",
+            reinterpret_cast<int*>( &m_Display.m_ShowTrackClearanceMode ),
+            PCB_DISPLAY_OPTIONS::SHOW_CLEARANCE_NEW_TRACKS_AND_VIA_AREAS ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "pcb_display.track_fill", &m_Display.m_DisplayPcbTrackFill, true ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "pcb_display.via_fill", &m_Display.m_DisplayViaFill, true ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "pcb_display.zone_mode", &m_Display.m_DisplayZonesMode, 0, 0, 2 ) );
+
+    m_params.emplace_back(
+            new PARAM<double>( "plot.line_width", &m_PlotLineWidth, 0.1, 0.01, 5.0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "cleanup.cleanup_vias",
+            &m_Cleanup.cleanup_vias, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "cleanup.merge_segments",
+            &m_Cleanup.merge_segments, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "cleanup.cleanup_unconnected",
+            &m_Cleanup.cleanup_unconnected, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "cleanup.cleanup_short_circuits",
+            &m_Cleanup.cleanup_short_circuits, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "cleanup.cleanup_tracks_in_pad",
+            &m_Cleanup.cleanup_tracks_in_pad, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "drc_dialog.refill_zones",
+            &m_DrcDialog.refill_zones, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "drc_dialog.test_track_to_zone",
+            &m_DrcDialog.test_track_to_zone, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "drc_dialog.test_footprints",
+            &m_DrcDialog.test_footprints, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "gen_drill.merge_pth_npth",
+            &m_GenDrill.merge_pth_npth, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "gen_drill.minimal_header",
+            &m_GenDrill.minimal_header, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "gen_drill.mirror", &m_GenDrill.mirror, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "gen_drill.unit_drill_is_inch",
+            &m_GenDrill.unit_drill_is_inch, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "gen_drill.use_route_for_oval_holes",
+            &m_GenDrill.use_route_for_oval_holes, true ) );
+
+    m_params.emplace_back( new PARAM<int>(
+            "gen_drill.drill_file_type", &m_GenDrill.drill_file_type, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>(
+            "gen_drill.map_file_type", &m_GenDrill.map_file_type, 1 ) );
+
+    m_params.emplace_back( new PARAM<int>(
+            "gen_drill.zeros_format", &m_GenDrill.zeros_format, 0, 0, 3 ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "export_idf.auto_adjust", &m_ExportIdf.auto_adjust, false ) );
+
+    m_params.emplace_back( new PARAM<int>( "export_idf.ref_units", &m_ExportIdf.ref_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<double>( "export_idf.ref_x", &m_ExportIdf.ref_x, 0 ) );
+
+    m_params.emplace_back( new PARAM<double>( "export_idf.ref_y", &m_ExportIdf.ref_y, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "export_idf.units_mils", &m_ExportIdf.units_mils, false ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "export_step.origin_mode", &m_ExportStep.origin_mode, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "export_step.origin_units", &m_ExportStep.origin_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<double>( "export_step.origin_x", &m_ExportStep.origin_x, 0 ) );
+
+    m_params.emplace_back( new PARAM<double>( "export_step.origin_y", &m_ExportStep.origin_y, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "export_step.no_virtual", &m_ExportStep.no_virtual, false ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "export_svg.black_and_white", &m_ExportSvg.black_and_white, false ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "export_svg.mirror", &m_ExportSvg.mirror, false ) );
+
+    m_params.emplace_back( new PARAM<bool>( "export_svg.one_file", &m_ExportSvg.one_file, false ) );
+
+    m_params.emplace_back(new PARAM<bool>(
+            "export_svg.plot_board_edges", &m_ExportSvg.plot_board_edges, true ) );
+
+    m_params.emplace_back( new PARAM<int>( "export_svg.page_size", &m_ExportSvg.page_size, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<wxString>( "export_svg.output_dir", &m_ExportSvg.output_dir, "" ) );
+
+    m_params.emplace_back( new PARAM_LIST<int>( "export_svg.layers", &m_ExportSvg.layers, {} ) );
+
+    m_params.emplace_back( new PARAM<int>( "export_vrml.units", &m_ExportVrml.units, 1 ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "export_vrml.copy_3d_models", &m_ExportVrml.copy_3d_models, false ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "export_vrml.use_relative_paths", &m_ExportVrml.use_relative_paths, false ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "export_vrml.use_plain_pcb", &m_ExportVrml.use_plain_pcb, false ) );
+
+    m_params.emplace_back( new PARAM<int>( "export_vrml.ref_units", &m_ExportVrml.ref_units, 0 ) );
+
+    m_params.emplace_back( new PARAM<double>( "export_vrml.ref_x", &m_ExportVrml.ref_x, 0 ) );
+
+    m_params.emplace_back( new PARAM<double>( "export_vrml.ref_y", &m_ExportVrml.ref_y, 0 ) );
+
+    m_params.emplace_back( new PARAM<int>( "zones.hatching_style", &m_Zones.hatching_style, 0 ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "zones.net_filter", &m_Zones.net_filter, "" ) );
+
+    m_params.emplace_back( new PARAM<int>( "zones.net_sort_mode", &m_Zones.net_sort_mode, 1 ) );
+
+    m_params.emplace_back(
+            new PARAM<double>( "zones.clearance", &m_Zones.clearance, ZONE_CLEARANCE_MIL ) );
+
+    m_params.emplace_back( new PARAM<double>( "zones.min_thickness",
+            &m_Zones.min_thickness, ZONE_THICKNESS_MIL ) );
+
+    m_params.emplace_back( new PARAM<double>( "zones.thermal_relief_gap",
+            &m_Zones.thermal_relief_gap, ZONE_THERMAL_RELIEF_GAP_MIL ) );
+
+    m_params.emplace_back( new PARAM<double>( "zones.thermal_relief_copper_width",
+            &m_Zones.thermal_relief_copper_width, ZONE_THERMAL_RELIEF_COPPER_WIDTH_MIL ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "import_graphics.layer", &m_ImportGraphics.layer, Dwgs_User ) );
+
+    m_params.emplace_back( new PARAM<bool>( "import_graphics.interactive_placement",
+            &m_ImportGraphics.interactive_placement, true ) );
+
+    m_params.emplace_back( new PARAM<int>(
+            "import_graphics.line_width_units", &m_ImportGraphics.line_width_units, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<double>( "import_graphics.line_width", &m_ImportGraphics.line_width, 0.2 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "import_graphics.origin_units", &m_ImportGraphics.origin_units, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<double>( "import_graphics.origin_x", &m_ImportGraphics.origin_x, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<double>( "import_graphics.origin_y", &m_ImportGraphics.origin_y, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "netlist.report_filter", &m_NetlistDialog.report_filter, -1 ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "netlist.update_footprints", &m_NetlistDialog.update_footprints, false ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "netlist.delete_shorting_tracks", &m_NetlistDialog.delete_shorting_tracks, false ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "netlist.delete_extra_footprints", &m_NetlistDialog.delete_extra_footprints, false ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "netlist.delete_single_pad_nets", &m_NetlistDialog.delete_single_pad_nets, false ) );
+
+    m_params.emplace_back(new PARAM<int>( "place_file.units", &m_PlaceFile.units, 1 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "place_file.file_options", &m_PlaceFile.file_options, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "place_file.file_format", &m_PlaceFile.file_format, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>(
+            "place_file.include_board_edge", &m_PlaceFile.include_board_edge, false ) );
+
+    m_params.emplace_back( new PARAM<int>( "plot.one_page_per_layer",
+            &m_Plot.one_page_per_layer, 1 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "plot.pads_drill_mode", &m_Plot.pads_drill_mode, 2 ) );
+
+    m_params.emplace_back( new PARAM<double>( "plot.fine_scale_x", &m_Plot.fine_scale_x, 0 ) );
+
+    m_params.emplace_back( new PARAM<double>( "plot.fine_scale_y", &m_Plot.fine_scale_y, 0 ) );
+
+    m_params.emplace_back(
+            new PARAM<double>( "plot.ps_fine_width_adjust", &m_Plot.ps_fine_width_adjust, 0 ) );
+
+    m_params.emplace_back( new PARAM<bool>( "plot.check_zones_before_plotting",
+            &m_Plot.check_zones_before_plotting, true ) );
+
+    m_params.emplace_back( new PARAM<wxString>( "window.footprint_text_shown_columns",
+            &m_FootprintTextShownColumns, "0 1 2 3 4 5 6" ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "footprint_wizard_list.width", &m_FootprintWizardList.width, -1 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "footprint_wizard_list.height", &m_FootprintWizardList.height, -1 ) );
+
+#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
+    m_params.emplace_back(
+            new PARAM_LIST<wxString>( "action_plugins.visible", &m_VisibleActionPlugins, {} ) );
+#endif
+
+    addParamsForWindow( &m_FootprintViewer, "footprint_viewer" );
+
+    addParamsForWindow( &m_FootprintWizard, "footprint_wizard" );
+}
+
+
+bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
+{
+    bool ret = APP_SETTINGS_BASE::MigrateFromLegacy( aCfg );
+
+    const std::string f = getLegacyFrameName();
+
+    ret &= fromLegacy<bool>( aCfg, "ShowLayerManagerTools",    "aui.show_layer_manager" );
+    ret &= fromLegacy<bool>( aCfg, "ShowMicrowaveTools",       "aui.show_microwave_tools" );
+
+    ret &= fromLegacy<int>(  aCfg, "FootprintChooserHSashPosition", "footprint_chooser.sash_h" );
+    ret &= fromLegacy<int>(  aCfg, "FootprintChooserVSashPosition", "footprint_chooser.sash_v" );
+    ret &= fromLegacy<int>(  aCfg, "FootprintChooserWidth",         "footprint_chooser.width" );
+    ret &= fromLegacy<int>(  aCfg, "FootprintChooserHeight",        "footprint_chooser.height" );
+
+    ret &= fromLegacy<int>(  aCfg, f + "FastGrid1",            "grid.fast_grid_1" );
+    ret &= fromLegacy<int>(  aCfg, f + "FastGrid2",            "grid.fast_grid_2" );
+
+    ret &= fromLegacy<bool>(  aCfg, "FlipLeftRight",           "editing.flip_left_right" );
+    ret &= fromLegacy<bool>(  aCfg, "MagneticGraphics",        "editing.magnetic_graphics" );
+    ret &= fromLegacy<int>(   aCfg, "MagneticPads",            "editing.magnetic_pads" );
+    ret &= fromLegacy<int>(   aCfg, "MagneticTracks",          "editing.magnetic_tracks" );
+    ret &= fromLegacy<bool>(  aCfg, "DisplayPolarCoords",      "editing.polar_coords" );
+    ret &= fromLegacy<bool>(  aCfg, "Use45DegreeGraphicSegments",
+                              "editing.use_45_degree_graphic_segments" );
+
+    ret &= fromLegacy<int>(  aCfg, f + "PcbUserGrid_X",        "grid.user.size_x" );
+    ret &= fromLegacy<int>(  aCfg, f + "PcbUserGrid_Y",        "grid.user.size_y" );
+    ret &= fromLegacy<int>(  aCfg, f + "PcbUserGrid_Unit",     "grid.user.units" );
+
+    ret &= fromLegacy<bool>(  aCfg, "PcbAffT",                 "pcb_display.graphic_items_fill" );
+    ret &= fromLegacy<int>(   aCfg, "MaxLnkS",                 "pcb_display.max_links_shown" );
+    ret &= fromLegacy<bool>(  aCfg, "ModAffC",                 "pcb_display.footprint_edge_fill" );
+    ret &= fromLegacy<bool>(  aCfg, "ModAffT",                 "pcb_display.footprint_text_fill" );
+    ret &= fromLegacy<int>(   aCfg, "ShowNetNamesMode",        "pcb_display.net_names_mode" );
+    ret &= fromLegacy<bool>(  aCfg, "PadAffG",                 "pcb_display.pad_clearance" );
+    ret &= fromLegacy<bool>(  aCfg, "PadFill",                 "pcb_display.pad_fill" );
+    ret &= fromLegacy<bool>(  aCfg, "PadSNum",                 "pcb_display.pad_numbers" );
+    ret &= fromLegacy<bool>(  aCfg, "ShowRatsnestLines",       "pcb_display.ratsnest_global" );
+    ret &= fromLegacy<bool>(  aCfg, "ShowRatsnestModuleLines", "pcb_display.ratsnest_footprint" );
+    ret &= fromLegacy<bool>(  aCfg, "CurvedRatsnestLines",     "pcb_display.ratsnest_curved" );
+    ret &= fromLegacy<int>(   aCfg, "RotationAngle",           "pcb_display.rotation_angle" );
+    ret &= fromLegacy<int>(   aCfg, "TrackDisplayClearance",   "pcb_display.track_clearance_mode" );
+    ret &= fromLegacy<bool>(  aCfg, "DisplayTrackFilled",      "pcb_display.track_fill" );
+    ret &= fromLegacy<bool>(  aCfg, "ViaFill",                 "pcb_display.via_fill" );
+    ret &= fromLegacy<int>(   aCfg, "PcbShowZonesMode",        "pcb_display.zone_mode" );
+
+    ret &= fromLegacy<double>( aCfg, "PlotLineWidth_mm",       "plot.line_width" );
+
+    aCfg->SetPath( "/dialogs/cleanup_tracks" );
+    ret &= fromLegacy<bool>(  aCfg, "DialogCleanupVias",         "cleanup.cleanup_vias" );
+    ret &= fromLegacy<bool>(  aCfg, "DialogCleanupMergeSegments", "cleanup.merge_segments" );
+    ret &= fromLegacy<bool>(  aCfg, "DialogCleanupUnconnected",  "cleanup.cleanup_unconnected" );
+    ret &= fromLegacy<bool>(  aCfg, "DialogCleanupShortCircuit", "cleanup.cleanup_short_circuits" );
+    ret &= fromLegacy<bool>(  aCfg, "DialogCleanupTracksInPads", "cleanup.cleanup_tracks_in_pad" );
+    aCfg->SetPath( "../.." );
+
+    ret &= fromLegacy<bool>(   aCfg, "RefillZonesBeforeDrc", "drc_dialog.refill_zones" );
+    ret &= fromLegacy<bool>(   aCfg, "DrcTrackToZoneTest",   "drc_dialog.test_track_to_zone" );
+    ret &= fromLegacy<bool>(   aCfg, "DrcTestFootprints",    "drc_dialog.test_footprints" );
+
+    ret &= fromLegacy<bool>(   aCfg, "DrillMergePTHNPTH",   "gen_drill.merge_pth_npth" );
+    ret &= fromLegacy<bool>(   aCfg, "DrillMinHeader",      "gen_drill.minimal_header" );
+    ret &= fromLegacy<bool>(   aCfg, "DrillMirrorYOpt",     "gen_drill.mirror" );
+    ret &= fromLegacy<bool>(   aCfg, "DrillUnit",           "gen_drill.unit_drill_is_inch" );
+    ret &= fromLegacy<bool>(   aCfg, "OvalHolesRouteMode",  "gen_drill.use_route_for_oval_holes" );
+    ret &= fromLegacy<int>(    aCfg, "DrillFileType",       "gen_drill.drill_file_type" );
+    ret &= fromLegacy<int>(    aCfg, "DrillMapFileType",    "gen_drill.map_file_type" );
+    ret &= fromLegacy<int>(    aCfg, "DrillZerosFormat",    "gen_drill.zeros_format" );
+
+    ret &= fromLegacy<bool>(   aCfg, "IDFRefAutoAdj",       "export_idf.auto_adjust" );
+    ret &= fromLegacy<int>(    aCfg, "IDFRefUnits",         "export_idf.ref_units" );
+    ret &= fromLegacy<double>( aCfg, "IDFRefX",             "export_idf.ref_x" );
+    ret &= fromLegacy<double>( aCfg, "IDFRefY",             "export_idf.ref_y" );
+    ret &= fromLegacy<bool>(   aCfg, "IDFExportThou",       "export_idf.units_mils" );
+
+    ret &= fromLegacy<int>(    aCfg, "STEP_Origin_Opt",      "export_step.origin_mode" );
+    ret &= fromLegacy<int>(    aCfg, "STEP_UserOriginUnits", "export_step.origin_units" );
+    ret &= fromLegacy<double>( aCfg, "STEP_UserOriginX",     "export_step.origin_x" );
+    ret &= fromLegacy<double>( aCfg, "STEP_UserOriginY",     "export_step.origin_y" );
+    ret &= fromLegacy<bool>(   aCfg, "STEP_NoVirtual",       "export_step.no_virtual" );
+
+    ret &= fromLegacy<bool>(   aCfg, "PlotSVGModeColor",     "export_svg.black_and_white" );
+    ret &= fromLegacy<bool>(   aCfg, "PlotSVGModeMirror",    "export_svg.mirror" );
+    ret &= fromLegacy<bool>(   aCfg, "PlotSVGModeOneFile",   "export_svg.one_file" );
+    ret &= fromLegacy<bool>(   aCfg, "PlotSVGBrdEdge",       "export_svg.plot_board_edges" );
+    ret &= fromLegacy<int>(    aCfg, "PlotSVGPageOpt",       "export_svg.page_size" );
+    ret &= fromLegacyString(   aCfg, "PlotSVGDirectory",     "export_svg.output_dir" );
+
+    {
+        nlohmann::json js = nlohmann::json::array();
+        wxString       key;
+        bool           val = false;
+
+        for( unsigned i = 0; i < PCB_LAYER_ID_COUNT; ++i  )
+        {
+            key.Printf( wxT( "PlotSVGLayer_%d" ), i );
+
+            if( aCfg->Read( key, &val ) && val )
+                js.push_back( i );
+        }
+
+        ( *this )[PointerFromString( "export_svg.layers" ) ] = js;
+    }
+
+    {
+        nlohmann::json js = nlohmann::json::array();
+
+        wxString packed;
+
+        if( aCfg->Read( "ActionPluginButtons", &packed ) )
+        {
+            wxStringTokenizer pluginSettingsTokenizer = wxStringTokenizer( packed, ";" );
+
+            while( pluginSettingsTokenizer.HasMoreTokens() )
+            {
+                wxString plugin = pluginSettingsTokenizer.GetNextToken();
+                wxStringTokenizer pluginTokenizer = wxStringTokenizer( plugin, "=" );
+
+                if( pluginTokenizer.CountTokens() != 2 )
+                {
+                    // Bad config
+                    continue;
+                }
+
+                plugin = pluginTokenizer.GetNextToken();
+
+                if( pluginTokenizer.GetNextToken().Cmp( wxT( "Visible" ) ) == 0 )
+                    js.push_back( plugin.ToUTF8() );
+            }
+        }
+
+        ( *this )[PointerFromString( "action_plugins.visible" ) ] = js;
+    }
+
+    ret &= fromLegacy<int>(    aCfg, "VrmlExportUnit",       "export_vrml.units" );
+    ret &= fromLegacy<bool>(   aCfg, "VrmlExportCopyFiles",  "export_vrml.copy_3d_models" );
+    ret &= fromLegacy<bool>(   aCfg, "VrmlUseRelativePaths", "export_vrml.use_relative_paths" );
+    ret &= fromLegacy<bool>(   aCfg, "VrmlUsePlainPCB",      "export_vrml.use_plain_pcb" );
+    ret &= fromLegacy<int>(    aCfg, "VrmlRefUnits",         "export_vrml.ref_units" );
+    ret &= fromLegacy<double>( aCfg, "VrmlRefX",             "export_vrml.ref_x" );
+    ret &= fromLegacy<double>( aCfg, "VrmlRefY",             "export_vrml.ref_y" );
+
+    ret &= fromLegacy<int>(    aCfg, "Zone_Ouline_Hatch_Opt", "zones.hatching_style" );
+    ret &= fromLegacyString(   aCfg, "Zone_Filter_Opt",       "zones.net_filter" );
+    ret &= fromLegacy<int>(    aCfg, "Zone_NetSort_Opt",      "zones.net_sort_mode" );
+    ret &= fromLegacy<double>( aCfg, "Zone_Clearance",        "zones.clearance" );
+    ret &= fromLegacy<double>( aCfg, "Zone_Thickness",        "zones.min_thickness" );
+    ret &= fromLegacy<double>( aCfg, "Zone_TH_Gap",           "zones.thermal_relief_gap" );
+    ret &= fromLegacy<double>( aCfg, "Zone_TH_Copper_Width",  "zones.thermal_relief_copper_width" );
+
+    aCfg->SetPath( "ImportGraphics" );
+    ret &= fromLegacy<int>(    aCfg, "BoardLayer",          "import_graphics.layer" );
+    ret &= fromLegacy<bool>(
+            aCfg, "InteractivePlacement", "import_graphics.interactive_placement" );
+    ret &= fromLegacyString(   aCfg, "LastFile",            "import_graphics.last_file" );
+    ret &= fromLegacy<double>( aCfg, "LineWidth",           "import_graphics.line_width" );
+    ret &= fromLegacy<int>(    aCfg, "LineWidthUnits",      "import_graphics.line_width_units" );
+    ret &= fromLegacy<int>(    aCfg, "PositionUnits",       "import_graphics.origin_units" );
+    ret &= fromLegacy<double>( aCfg, "PositionX",           "import_graphics.origin_x" );
+    ret &= fromLegacy<double>( aCfg, "PositionY",           "import_graphics.origin_y" );
+    aCfg->SetPath( ".." );
+
+    ret &= fromLegacy<int>(  aCfg, "NetlistReportFilterMsg",  "netlist.report_filter" );
+    ret &= fromLegacy<bool>( aCfg, "NetlistUpdateFootprints", "netlist.update_footprints" );
+    ret &= fromLegacy<bool>( aCfg,
+            "NetlistDeleteShortingTracks", "netlist.delete_shorting_tracks" );
+    ret &= fromLegacy<bool>( aCfg,
+            "NetlistDeleteExtraFootprints", "netlist.delete_extra_footprints" );
+    ret &= fromLegacy<bool>( aCfg, "NetlistDeleteSinglePadNets", "netlist.delete_single_pad_nets" );
+
+    ret &= fromLegacy<int>(    aCfg, "PlaceFileUnits",          "place_file.units" );
+    ret &= fromLegacy<int>(    aCfg, "PlaceFileOpts",           "place_file.file_options" );
+    ret &= fromLegacy<int>(    aCfg, "PlaceFileFormat",         "place_file.file_format" );
+    ret &= fromLegacy<bool>(   aCfg, "PlaceFileIncludeBrdEdge", "place_file.include_board_edge" );
+
+    ret &= fromLegacy<int>(    aCfg, "PrintSinglePage",        "plot.one_page_per_layer" );
+    ret &= fromLegacy<int>(    aCfg, "PrintPadsDrillOpt",      "plot.pads_drill_mode" );
+    ret &= fromLegacy<double>( aCfg, "PlotXFineScaleAdj",      "plot.fine_scale_x" );
+    ret &= fromLegacy<double>( aCfg, "PlotYFineScaleAdj",      "plot.fine_scale_y" );
+    ret &= fromLegacy<double>( aCfg, "PSPlotFineWidthAdj",     "plot.ps_fine_width_adjust" );
+    ret &= fromLegacy<bool>( aCfg, "CheckZonesBeforePlotting", "plot.check_zones_before_plotting" );
+
+    ret &= fromLegacyString( aCfg,
+            "FootprintTextShownColumns", "window.footprint_text_shown_columns" );
+
+    ret &= fromLegacy<int>(    aCfg, "FpWizardListWidth",        "footprint_wizard_list.width" );
+    ret &= fromLegacy<int>(    aCfg, "FpWizardListHeight",       "footprint_wizard_list.height" );
+
+    migrateWindowConfig( aCfg, "ModViewFrame", "footprint_viewer" );
+
+    migrateWindowConfig( aCfg, "FootprintWizard", "footprint_wizard" );
+    ret &= fromLegacyString( aCfg, "Fpwizard_auiPerspective", "footprint_wizard.perspective" );
+
+
+    const std::string p = "pcbnew.InteractiveRouter.";
+
+    ( *this )[PointerFromString( "tools.pns.meta" ) ] = nlohmann::json( {
+                { "filename", "pns" },
+                { "version", 0 }
+            } );
+
+    ret &= fromLegacy<int>(  aCfg, p + "Mode",                  "tools.pns.mode" );
+    ret &= fromLegacy<int>(  aCfg, p + "OptimizerEffort",       "tools.pns.effort" );
+    ret &= fromLegacy<bool>( aCfg, p + "RemoveLoops",           "tools.pns.remove_loops" );
+    ret &= fromLegacy<bool>( aCfg, p + "SmartPads",             "tools.pns.smart_pads" );
+    ret &= fromLegacy<bool>( aCfg, p + "ShoveVias",             "tools.pns.shove_vias" );
+    ret &= fromLegacy<bool>( aCfg, p + "StartDiagonal",         "tools.pns.start_diagonal" );
+    ret &= fromLegacy<int>(  aCfg, p + "ShoveTimeLimit",        "tools.pns.shove_time_limit" );
+    ret &= fromLegacy<int>(  aCfg, p + "ShoveIterationLimit",   "tools.pns.shove_iteration_limit" );
+    ret &= fromLegacy<int>(  aCfg,
+            p + "WalkaroundIterationLimit", "tools.pns.walkaround_iteration_limit" );
+    ret &= fromLegacy<bool>( aCfg, p + "JumpOverObstacles",     "tools.pns.jump_over_obstacles" );
+    ret &= fromLegacy<bool>( aCfg,
+            p + "SmoothDraggedSegments", "tools.pns.smooth_dragged_segments" );
+    ret &= fromLegacy<bool>( aCfg, p + "CanViolateDRC",         "tools.pns.can_violate_drc" );
+    ret &= fromLegacy<bool>( aCfg, p + "SuggestFinish",         "tools.pns.suggest_finish" );
+    ret &= fromLegacy<bool>( aCfg, p + "FreeAngleMode",         "tools.pns.free_angle_mode" );
+    ret &= fromLegacy<bool>( aCfg, p + "InlineDragEnabled",     "tools.pns.inline_drag" );
+
+    // Migrate color settings that were stored in the pcbnew config file
+
+    COLOR_SETTINGS* cs = Pgm().GetSettingsManager().GetColorSettings();
+
+    auto migrateLegacyColor = [&] ( const std::string& aKey, int aLayerId ) {
+        wxString str;
+
+        if( aCfg->Read( aKey, &str ) )
+            cs->SetColor( aLayerId, COLOR4D( str ) );
+    };
+
+    for( int i = 0; i < PCB_LAYER_ID_COUNT; ++i )
+    {
+        wxString layer = LSET::Name( PCB_LAYER_ID( i ) );
+        migrateLegacyColor( "Color4DPCBLayer_" + layer.ToStdString(), PCB_LAYER_ID( i ) );
+    }
+
+    migrateLegacyColor( "Color4DAnchorEx",           LAYER_ANCHOR );
+    migrateLegacyColor( "Color4DAuxItems",           LAYER_AUX_ITEMS );
+    migrateLegacyColor( "Color4DGrid",               LAYER_GRID );
+    migrateLegacyColor( "Color4DNoNetPadMarker",     LAYER_NO_CONNECTS );
+    migrateLegacyColor( "Color4DNonPlatedEx",        LAYER_NON_PLATEDHOLES );
+    migrateLegacyColor( "Color4DPadBackEx",          LAYER_PAD_BK );
+    migrateLegacyColor( "Color4DPadFrontEx",         LAYER_PAD_FR );
+    migrateLegacyColor( "Color4DPadThruHoleEx",      LAYER_PADS_TH );
+    migrateLegacyColor( "Color4DPCBBackground",      LAYER_PCB_BACKGROUND );
+    migrateLegacyColor( "Color4DPCBCursor",          LAYER_CURSOR );
+    migrateLegacyColor( "Color4DRatsEx",             LAYER_RATSNEST );
+    migrateLegacyColor( "Color4DTxtBackEx",          LAYER_MOD_TEXT_BK );
+    migrateLegacyColor( "Color4DTxtFrontEx",         LAYER_MOD_TEXT_FR );
+    migrateLegacyColor( "Color4DTxtInvisEx",         LAYER_MOD_TEXT_INVISIBLE );
+    migrateLegacyColor( "Color4DViaBBlindEx",        LAYER_VIA_BBLIND );
+    migrateLegacyColor( "Color4DViaMicroEx",         LAYER_VIA_MICROVIA );
+    migrateLegacyColor( "Color4DViaThruEx",          LAYER_VIA_THROUGH );
+    migrateLegacyColor( "Color4DWorksheet",          LAYER_WORKSHEET );
+
+    // Footprint editor settings were stored in pcbnew config file.  Migrate them here.
+    auto fpedit = Pgm().GetSettingsManager().GetAppSettings<FOOTPRINT_EDITOR_SETTINGS>( false );
+    fpedit->MigrateFromLegacy( aCfg );
+    fpedit->Load();
+
+    // Same with 3D viewer
+    auto viewer3d = Pgm().GetSettingsManager().GetAppSettings<EDA_3D_VIEWER_SETTINGS>( false );
+    viewer3d->MigrateFromLegacy( aCfg );
+    viewer3d->Load();
+
+    return ret;
+}
\ No newline at end of file
diff --git a/pcbnew/pcbnew_settings.h b/pcbnew/pcbnew_settings.h
new file mode 100644
index 0000000000..41c8391ded
--- /dev/null
+++ b/pcbnew/pcbnew_settings.h
@@ -0,0 +1,269 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2020 Jon Evans <jon@craftyjon.com>
+ * Copyright (C) 2020 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 PCBNEW_SETTINGS_H_
+#define PCBNEW_SETTINGS_H_
+
+#include <settings/app_settings.h>
+#include <pcb_display_options.h>
+
+namespace PNS
+{
+    class ROUTING_SETTINGS;
+}
+
+enum class MAGNETIC_OPTIONS
+{
+    NO_EFFECT,
+    CAPTURE_CURSOR_IN_TRACK_TOOL,
+    CAPTURE_ALWAYS
+};
+
+
+class PCBNEW_SETTINGS : public APP_SETTINGS_BASE
+{
+public:
+    struct AUI_PANELS
+    {
+        bool show_microwave_tools;
+        bool show_layer_manager;
+    };
+
+    struct DIALOG_CLEANUP
+    {
+        bool cleanup_vias;
+        bool cleanup_tracks_in_pad;
+        bool cleanup_unconnected;
+        bool cleanup_short_circuits;
+        bool merge_segments;
+    };
+
+    struct DIALOG_DRC
+    {
+        bool refill_zones;
+        bool test_track_to_zone;
+        bool test_footprints;
+    };
+
+    struct DIALOG_EXPORT_IDF
+    {
+        bool   auto_adjust;
+        int    ref_units;
+        double ref_x;
+        double ref_y;
+        bool   units_mils;
+    };
+
+    struct DIALOG_EXPORT_STEP
+    {
+        int    origin_mode;
+        int    origin_units;
+        double origin_x;
+        double origin_y;
+        bool   no_virtual;
+    };
+
+    struct DIALOG_EXPORT_SVG
+    {
+        bool             black_and_white;
+        bool             mirror;
+        bool             one_file;
+        bool             plot_board_edges;
+        int              page_size;
+        wxString         output_dir;
+        std::vector<int> layers;
+    };
+
+    struct DIALOG_EXPORT_VRML
+    {
+        int    units;
+        bool   copy_3d_models;
+        bool   use_relative_paths;
+        bool   use_plain_pcb;
+        int    ref_units;
+        double ref_x;
+        double ref_y;
+    };
+
+    struct DIALOG_FOOTPRINT_WIZARD_LIST
+    {
+        int width;
+        int height;
+    };
+
+    struct DIALOG_GENERATE_DRILL
+    {
+        bool merge_pth_npth;
+        bool minimal_header;
+        bool mirror;
+        bool unit_drill_is_inch;
+        bool use_route_for_oval_holes;
+        int  drill_file_type;
+        int  map_file_type;
+        int  zeros_format;
+    };
+
+    struct DIALOG_IMPORT_GRAPHICS
+    {
+        int         layer;
+        bool        interactive_placement;
+        wxString    last_file;
+        double      line_width;
+        int         line_width_units;
+        int         origin_units;
+        double      origin_x;
+        double      origin_y;
+    };
+
+    struct DIALOG_NETLIST
+    {
+        int  report_filter;
+        bool update_footprints;
+        bool delete_shorting_tracks;
+        bool delete_extra_footprints;
+        bool delete_single_pad_nets;
+    };
+
+    struct DIALOG_PLACE_FILE
+    {
+        int  units;
+        int  file_options;
+        int  file_format;
+        bool include_board_edge;
+    };
+
+    struct DIALOG_PLOT
+    {
+        int    one_page_per_layer;
+        int    pads_drill_mode;
+        double fine_scale_x;
+        double fine_scale_y;
+        double ps_fine_width_adjust;
+        bool   check_zones_before_plotting;
+    };
+
+    struct FOOTPRINT_CHOOSER
+    {
+        int width;
+        int height;
+        int sash_h;
+        int sash_v;
+    };
+
+    struct USER_GRID
+    {
+        double size_x;
+        double size_y;
+        int    units;
+    };
+
+    struct ZONES
+    {
+        int         hatching_style;
+        wxString    net_filter;
+        int         net_sort_mode;
+        double      clearance;
+        double      min_thickness;
+        double      thermal_relief_gap;
+        double      thermal_relief_copper_width;
+    };
+
+    PCBNEW_SETTINGS();
+
+    virtual ~PCBNEW_SETTINGS() {}
+
+    virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
+
+    AUI_PANELS m_AuiPanels;
+
+    DIALOG_CLEANUP m_Cleanup;
+
+    DIALOG_DRC m_DrcDialog;
+
+    DIALOG_EXPORT_IDF m_ExportIdf;
+
+    DIALOG_EXPORT_STEP m_ExportStep;
+
+    DIALOG_EXPORT_SVG m_ExportSvg;
+
+    DIALOG_EXPORT_VRML m_ExportVrml;
+
+    DIALOG_FOOTPRINT_WIZARD_LIST m_FootprintWizardList;
+
+    DIALOG_GENERATE_DRILL m_GenDrill;
+
+    DIALOG_IMPORT_GRAPHICS m_ImportGraphics;
+
+    DIALOG_NETLIST m_NetlistDialog;
+
+    DIALOG_PLACE_FILE m_PlaceFile;
+
+    DIALOG_PLOT m_Plot;
+
+    FOOTPRINT_CHOOSER m_FootprintChooser;
+
+    USER_GRID m_UserGrid;
+
+    ZONES m_Zones;
+
+    WINDOW_SETTINGS m_FootprintViewer;
+
+    WINDOW_SETTINGS m_FootprintWizard;
+
+    PCB_DISPLAY_OPTIONS m_Display;
+
+    int m_FastGrid1;
+
+    int m_FastGrid2;
+
+    bool m_Use45DegreeGraphicSegments;   // True to constraint graphic lines to horizontal,
+    // vertical and 45ยบ
+    bool m_FlipLeftRight;                // True: Flip footprints across Y axis
+    // False: Flip footprints across X axis
+
+    bool m_PolarCoords;
+
+    int m_RotationAngle;
+
+    double m_PlotLineWidth;
+
+    bool m_ShowPageLimits;
+
+    wxString m_FootprintTextShownColumns;
+
+    MAGNETIC_OPTIONS m_MagneticPads;
+
+    MAGNETIC_OPTIONS m_MagneticTracks;
+
+    bool             m_MagneticGraphics;
+
+    PNS::ROUTING_SETTINGS* m_PnsSettings;
+
+#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
+    std::vector<wxString> m_VisibleActionPlugins;
+#endif
+
+protected:
+
+    virtual std::string getLegacyFrameName() const override { return "PcbFrame"; }
+
+};
+
+#endif
diff --git a/pcbnew/pcbplot.h b/pcbnew/pcbplot.h
index 668800cd10..25d545f72d 100644
--- a/pcbnew/pcbplot.h
+++ b/pcbnew/pcbplot.h
@@ -29,11 +29,14 @@
 #ifndef PCBPLOT_H_
 #define PCBPLOT_H_
 
-#include <wx/filename.h>
+#include <layers_id_colors_and_visibility.h>
+#include <math/util.h> // for KiROUND
 #include <pad_shapes.h>
 #include <pcb_plot_params.h>
-#include <layers_id_colors_and_visibility.h>
-#include <math/util.h>      // for KiROUND
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/settings_manager.h>
+#include <wx/filename.h>
 
 class PLOTTER;
 class TEXTE_PCB;
@@ -48,22 +51,6 @@ class ZONE_CONTAINER;
 class BOARD;
 class REPORTER;
 
-///@{
-/// \ingroup config
-
-#define OPTKEY_LAYERBASE             wxT( "PlotLayer_%d" )
-#define OPTKEY_PRINT_LINE_WIDTH      wxT( "PrintLineWidth" )
-#define OPTKEY_PRINT_SCALE           wxT( "PrintScale" )
-#define OPTKEY_PRINT_PAGE_FRAME      wxT( "PrintPageFrame" )
-#define OPTKEY_PRINT_MONOCHROME_MODE wxT( "PrintMonochrome" )
-#define OPTKEY_PRINT_PAGE_PER_LAYER  wxT( "PrintSinglePage" )
-#define OPTKEY_PRINT_PADS_DRILL      wxT( "PrintPadsDrillOpt" )
-#define OPTKEY_PLOT_X_FINESCALE_ADJ  wxT( "PlotXFineScaleAdj" )
-#define OPTKEY_PLOT_Y_FINESCALE_ADJ  wxT( "PlotYFineScaleAdj" )
-#define CONFIG_PS_FINEWIDTH_ADJ      wxT( "PSPlotFineWidthAdj" )
-#define OPTKEY_PLOT_CHECK_ZONES      wxT( "CheckZonesBeforePlotting" )
-
-///@}
 
 // Define min and max reasonable values for plot/print scale
 #define PLOT_MIN_SCALE 0.01
@@ -80,12 +67,18 @@ class BRDITEMS_PLOTTER : public PCB_PLOT_PARAMS
     BOARD*      m_board;
     LSET        m_layerMask;
 
+    /// Pointer to color settings that should be used for plotting
+    COLOR_SETTINGS* m_colors;
+
 public:
     BRDITEMS_PLOTTER( PLOTTER* aPlotter, BOARD* aBoard, const PCB_PLOT_PARAMS& aPlotOpts ) :
         PCB_PLOT_PARAMS( aPlotOpts )
     {
         m_plotter = aPlotter;
         m_board = aBoard;
+
+        // TODO(JE) do we ever need to plot outside the context of Pgm()?
+        m_colors = Pgm().GetSettingsManager().GetColorSettings();
     }
 
     /**
diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp
index e60d475646..39ba4ea4ae 100644
--- a/pcbnew/plot_board_layers.cpp
+++ b/pcbnew/plot_board_layers.cpp
@@ -101,10 +101,13 @@ void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
                 COLOR4D color = COLOR4D::BLACK;
 
                 if( layersmask_plotpads[B_SilkS] )
-                   color = aBoard->Colors().GetLayerColor( B_SilkS );
+                   color = aPlotter->ColorSettings()->GetColor( B_SilkS );
 
                 if( layersmask_plotpads[F_SilkS] )
-                    color = ( color == COLOR4D::BLACK) ? aBoard->Colors().GetLayerColor( F_SilkS ) : color;
+                {
+                    color = ( color == COLOR4D::BLACK ) ?
+                            aPlotter->ColorSettings()->GetColor( F_SilkS ) : color;
+                }
 
                 itemplotter.PlotPad( pad, color, SKETCH );
             }
@@ -404,10 +407,10 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
             COLOR4D color = COLOR4D::BLACK;
 
             if( pad->GetLayerSet()[B_Cu] )
-               color = aBoard->Colors().GetItemColor( LAYER_PAD_BK );
+               color = aPlotOpt.ColorSettings()->GetColor( LAYER_PAD_BK );
 
             if( pad->GetLayerSet()[F_Cu] )
-                color = color.LegacyMix( aBoard->Colors().GetItemColor( LAYER_PAD_FR ) );
+                color = color.LegacyMix( aPlotOpt.ColorSettings()->GetColor( LAYER_PAD_FR ) );
 
             // Temporary set the pad size to the required plot size:
             wxSize tmppadsize = pad->GetSize();
@@ -530,11 +533,11 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter,
 
         gbr_metadata.SetNetName( Via->GetNetname() );
 
-        COLOR4D color =
-                aBoard->Colors().GetItemColor( LAYER_VIAS + static_cast<int>( Via->GetViaType() ) );
+        COLOR4D color = aPlotOpt.ColorSettings()->GetColor(
+                LAYER_VIAS + static_cast<int>( Via->GetViaType() ) );
         // Set plot color (change WHITE to LIGHTGRAY because the white items are not seen on a
         // white paper or screen
-        aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY);
+        aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY );
         aPlotter->FlashPadCircle( Via->GetStart(), diameter, plotMode, &gbr_metadata );
     }
 
@@ -997,6 +1000,8 @@ static void initializePlotter( PLOTTER *aPlotter, BOARD * aBoard,
     aPlotter->SetCreator( wxT( "PCBNEW" ) );
     aPlotter->SetColorMode( false );        // default is plot in Black and White.
     aPlotter->SetTextMode( aPlotOpts->GetTextMode() );
+
+    aPlotter->SetColorSettings( aPlotOpts->ColorSettings() );
 }
 
 
diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp
index d9f9bc44e7..b82f95a99e 100644
--- a/pcbnew/plot_brditems_plotter.cpp
+++ b/pcbnew/plot_brditems_plotter.cpp
@@ -40,7 +40,6 @@
 
 #include <board_design_settings.h>            // for BOARD_DESIGN_SETTINGS
 #include <colors.h>                           // for LIGHTGRAY, WHITE
-#include <colors_design_settings.h>           // for COLORS_DESIGN_SETTINGS
 #include <core/typeinfo.h>                    // for dyn_cast, PCB_DIMENSION_T
 #include <eda_text.h>                         // for FILLED, EDA_DRAW_MODE_T
 #include <gal/color4d.h>                      // for COLOR4D, operator!=
@@ -74,7 +73,7 @@
 
 COLOR4D BRDITEMS_PLOTTER::getColor( LAYER_NUM aLayer )
 {
-    COLOR4D color = m_board->Colors().GetLayerColor( aLayer );
+    COLOR4D color = m_colors->GetColor( aLayer );
 
     // A hack to avoid plotting ahite itmen in white color, expecting the paper
     // is also white: use a non white color:
@@ -394,7 +393,7 @@ void BRDITEMS_PLOTTER::PlotDimension( DIMENSION* aDim )
     draw.SetWidth( aDim->GetWidth() );
     draw.SetLayer( aDim->GetLayer() );
 
-    COLOR4D color = m_board->Colors().GetLayerColor( aDim->GetLayer() );
+    COLOR4D color = m_colors->GetColor( aDim->GetLayer() );
 
     // Set plot color (change WHITE to LIGHTGRAY because
     // the white items are not seen on a white paper or screen
diff --git a/pcbnew/python/kicad_pyshell/__init__.py b/pcbnew/python/kicad_pyshell/__init__.py
index 91bca5b1fc..b7bae757c8 100644
--- a/pcbnew/python/kicad_pyshell/__init__.py
+++ b/pcbnew/python/kicad_pyshell/__init__.py
@@ -71,7 +71,7 @@ class PcbnewPyShell(editor.EditorNotebookFrame):
             module.__dict__['__builtins__'] = __builtin__
         namespace = module.__dict__.copy()
 
-        self.config_dir = pcbnew.GetKicadConfigPath()
+        self.config_dir = pcbnew.SETTINGS_MANAGER.GetUserSettingsPath()
         self.dataDir = self.config_dir
 
         self._setup_startup()
diff --git a/pcbnew/router/length_tuner_tool.cpp b/pcbnew/router/length_tuner_tool.cpp
index 32a06775a3..363992957c 100644
--- a/pcbnew/router/length_tuner_tool.cpp
+++ b/pcbnew/router/length_tuner_tool.cpp
@@ -305,7 +305,6 @@ int LENGTH_TUNER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
     frame()->UndoRedoBlock( false );
 
     // Store routing settings till the next invocation
-    m_savedSettings = m_router->Settings();
     m_savedSizes = m_router->Sizes();
 
     frame()->PopTool( tool );
diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp
index 2900691123..3c3f6a1eba 100644
--- a/pcbnew/router/pns_router.cpp
+++ b/pcbnew/router/pns_router.cpp
@@ -29,7 +29,11 @@
 #include <gal/graphics_abstraction_layer.h>
 #include <gal/color4d.h>
 
+#include <pgm_base.h>
+#include <settings/settings_manager.h>
+
 #include <pcb_painter.h>
+#include <pcbnew_settings.h>
 
 #include <geometry/shape.h>
 #include <geometry/shape_line_chain.h>
@@ -67,6 +71,7 @@ ROUTER::ROUTER()
     // Initialize all other variables:
     m_lastNode = nullptr;
     m_iterLimit = 0;
+    m_settings = nullptr;
     m_showInterSteps = false;
     m_snapshotIter = 0;
     m_violation = false;
diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h
index c4ebe2ddf1..0e2bb13823 100644
--- a/pcbnew/router/pns_router.h
+++ b/pcbnew/router/pns_router.h
@@ -187,7 +187,7 @@ public:
     bool GetShowIntermediateSteps() const { return m_showInterSteps; }
     int GetShapshotIter() const { return m_snapshotIter; }
 
-    ROUTING_SETTINGS& Settings() { return m_settings; }
+    ROUTING_SETTINGS& Settings() { return *m_settings; }
 
     void CommitRouting( NODE* aNode );
 
@@ -201,7 +201,7 @@ public:
      * Changes routing settings to ones passed in the parameter.
      * @param aSettings are the new settings.
      */
-    void LoadSettings( const ROUTING_SETTINGS& aSettings )
+    void LoadSettings( ROUTING_SETTINGS* aSettings )
     {
         m_settings = aSettings;
     }
@@ -268,7 +268,7 @@ private:
     bool m_violation;
     bool m_forceMarkObstaclesMode = false;
 
-    ROUTING_SETTINGS m_settings;
+    ROUTING_SETTINGS* m_settings;
     SIZES_SETTINGS m_sizes;
     ROUTER_MODE m_mode;
 
diff --git a/pcbnew/router/pns_routing_settings.cpp b/pcbnew/router/pns_routing_settings.cpp
index 9cba63334b..1d7d3359bd 100644
--- a/pcbnew/router/pns_routing_settings.cpp
+++ b/pcbnew/router/pns_routing_settings.cpp
@@ -19,15 +19,18 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <tool/tool_settings.h>
-
 #include <geometry/direction45.h>
+#include <settings/parameters.h>
 
 #include "pns_routing_settings.h"
 
 namespace PNS {
 
-ROUTING_SETTINGS::ROUTING_SETTINGS()
+const int pnsSchemaVersion = 0;
+
+
+ROUTING_SETTINGS::ROUTING_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
+        NESTED_SETTINGS( "pns", pnsSchemaVersion, aParent, aPath )
 {
     m_routingMode = RM_Walkaround;
     m_optimizerEffort = OE_MEDIUM;
@@ -47,46 +50,39 @@ ROUTING_SETTINGS::ROUTING_SETTINGS()
     m_inlineDragEnabled = false;
     m_snapToTracks = false;
     m_snapToPads = false;
-}
 
+    m_params.emplace_back( new PARAM<int>( "mode", reinterpret_cast<int*>( &m_routingMode ),
+            static_cast<int>( RM_Walkaround ) ) );
 
-void ROUTING_SETTINGS::Save( TOOL_SETTINGS& aSettings ) const
-{
-    aSettings.Set( "Mode", (int) m_routingMode );
-    aSettings.Set( "OptimizerEffort", (int) m_optimizerEffort );
-    aSettings.Set( "RemoveLoops", m_removeLoops );
-    aSettings.Set( "SmartPads", m_smartPads );
-    aSettings.Set( "ShoveVias", m_shoveVias );
-    aSettings.Set( "StartDiagonal", m_startDiagonal );
-    aSettings.Set( "ShoveTimeLimit", m_shoveTimeLimit.Get() );
-    aSettings.Set( "ShoveIterationLimit", m_shoveIterationLimit );
-    aSettings.Set( "WalkaroundIterationLimit", m_walkaroundIterationLimit );
-    aSettings.Set( "JumpOverObstacles", m_jumpOverObstacles );
-    aSettings.Set( "SmoothDraggedSegments", m_smoothDraggedSegments );
-    aSettings.Set( "CanViolateDRC", m_canViolateDRC );
-    aSettings.Set( "SuggestFinish", m_suggestFinish );
-    aSettings.Set( "FreeAngleMode", m_freeAngleMode );
-    aSettings.Set( "InlineDragEnabled", m_inlineDragEnabled );
-}
+    m_params.emplace_back( new PARAM<int>( "effort", reinterpret_cast<int*>( &m_optimizerEffort ),
+            static_cast<int>( OE_MEDIUM ) ) );
 
+    m_params.emplace_back( new PARAM<bool>( "remove_loops",     &m_removeLoops,     true ) );
+    m_params.emplace_back( new PARAM<bool>( "smart_pads",       &m_smartPads,       true ) );
+    m_params.emplace_back( new PARAM<bool>( "shove_vias",       &m_shoveVias,       true ) );
+    m_params.emplace_back( new PARAM<bool>( "suggest_finish",   &m_suggestFinish,   false ) );
+    m_params.emplace_back( new PARAM<bool>( "follow_mouse",     &m_followMouse,     true ) );
+    m_params.emplace_back( new PARAM<bool>( "start_diagonal",   &m_startDiagonal,   false ) );
+    m_params.emplace_back( new PARAM<int>( "shove_iteration_limit", &m_shoveIterationLimit, 250 ) );
 
-void ROUTING_SETTINGS::Load( const TOOL_SETTINGS& aSettings )
-{
-    m_routingMode = (PNS_MODE) aSettings.Get( "Mode", (int) RM_Walkaround );
-    m_optimizerEffort = (PNS_OPTIMIZATION_EFFORT) aSettings.Get( "OptimizerEffort", (int) OE_MEDIUM );
-    m_removeLoops = aSettings.Get( "RemoveLoops", true );
-    m_smartPads = aSettings.Get( "SmartPads", true );
-    m_shoveVias = aSettings.Get( "ShoveVias", true );
-    m_startDiagonal = aSettings.Get( "StartDiagonal", false );
-    m_shoveTimeLimit.Set( aSettings.Get( "ShoveTimeLimit", 1000 ) );
-    m_shoveIterationLimit = aSettings.Get( "ShoveIterationLimit", 250 );
-    m_walkaroundIterationLimit = aSettings.Get( "WalkaroundIterationLimit", 50 );
-    m_jumpOverObstacles = aSettings.Get( "JumpOverObstacles", false  );
-    m_smoothDraggedSegments = aSettings.Get( "SmoothDraggedSegments", true );
-    m_canViolateDRC = aSettings.Get( "CanViolateDRC", false );
-    m_suggestFinish = aSettings.Get( "SuggestFinish", false );
-    m_freeAngleMode = aSettings.Get( "FreeAngleMode", false );
-    m_inlineDragEnabled = aSettings.Get( "InlineDragEnabled", false );
+    m_params.emplace_back( new PARAM_LAMBDA<int>( "shove_time_limit", [this] () -> int {
+                return m_shoveTimeLimit.Get();
+            }, [this] ( int aVal ) {
+                m_shoveTimeLimit.Set( aVal );
+            }, 1000 ) );
+
+    m_params.emplace_back(
+            new PARAM<int>( "walkaround_iteration_limit", &m_walkaroundIterationLimit, 40 ) );
+    m_params.emplace_back( new PARAM<bool>( "jump_over_obstacles", &m_jumpOverObstacles, false ) );
+
+    m_params.emplace_back(
+            new PARAM<bool>( "smooth_dragged_segments", &m_smoothDraggedSegments, true ) );
+
+    m_params.emplace_back( new PARAM<bool>( "can_violate_drc",  &m_canViolateDRC,     false ) );
+    m_params.emplace_back( new PARAM<bool>( "free_angle_mode",  &m_freeAngleMode,     false ) );
+    m_params.emplace_back( new PARAM<bool>( "inline_drag",      &m_inlineDragEnabled, false ) );
+    m_params.emplace_back( new PARAM<bool>( "snap_to_tracks",   &m_snapToTracks,      false ) );
+    m_params.emplace_back( new PARAM<bool>( "snap_to_pads",     &m_snapToPads,        false ) );
 }
 
 
diff --git a/pcbnew/router/pns_routing_settings.h b/pcbnew/router/pns_routing_settings.h
index e537753d69..72ed2af396 100644
--- a/pcbnew/router/pns_routing_settings.h
+++ b/pcbnew/router/pns_routing_settings.h
@@ -24,6 +24,8 @@
 
 #include <cstdio>
 
+#include <settings/nested_settings.h>
+
 #include "time_limit.h"
 
 class DIRECTION_45;
@@ -54,13 +56,10 @@ enum PNS_OPTIMIZATION_EFFORT
  * Contains all persistent settings of the router, such as the mode, optimization effort, etc.
  */
 
-class ROUTING_SETTINGS
+class ROUTING_SETTINGS : public NESTED_SETTINGS
 {
 public:
-    ROUTING_SETTINGS();
-
-    void Load( const TOOL_SETTINGS& where );
-    void Save( TOOL_SETTINGS& where ) const;
+    ROUTING_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath );
 
     ///> Returns the routing mode.
     PNS_MODE Mode() const { return m_routingMode; }
diff --git a/pcbnew/router/pns_tool_base.cpp b/pcbnew/router/pns_tool_base.cpp
index 0b3696bf51..5342d870eb 100644
--- a/pcbnew/router/pns_tool_base.cpp
+++ b/pcbnew/router/pns_tool_base.cpp
@@ -32,6 +32,7 @@ using namespace std::placeholders;
 #include <macros.h>
 #include <view/view_controls.h>
 #include <pcb_painter.h>
+#include <pcbnew_settings.h>
 #include <dialogs/dialog_pns_settings.h>
 #include <dialogs/dialog_pns_diff_pair_dimensions.h>
 #include <dialogs/dialog_pns_length_tuning_settings.h>
@@ -103,9 +104,13 @@ void TOOL_BASE::Reset( RESET_REASON aReason )
     m_router->SetInterface( m_iface );
     m_router->ClearWorld();
     m_router->SyncWorld();
-    m_router->LoadSettings( m_savedSettings );
+
     m_router->UpdateSizes( m_savedSizes );
 
+    auto settings = new PNS::ROUTING_SETTINGS( frame()->GetSettings(), "tools.pns" );
+    frame()->GetSettings()->m_PnsSettings = settings;
+    m_router->LoadSettings( frame()->GetSettings()->m_PnsSettings );
+
     m_gridHelper = new GRID_HELPER( frame() );
 }
 
@@ -241,11 +246,13 @@ bool TOOL_BASE::checkSnap( ITEM *aItem )
     // Sync PNS engine settings with the general PCB editor options.
     auto& pnss = m_router->Settings();
 
-    pnss.SetSnapToPads( frame()->Settings().m_MagneticPads == CAPTURE_CURSOR_IN_TRACK_TOOL
-                     || frame()->Settings().m_MagneticPads == CAPTURE_ALWAYS );
+    pnss.SetSnapToPads(
+            frame()->Settings().m_MagneticPads == MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL ||
+            frame()->Settings().m_MagneticPads == MAGNETIC_OPTIONS::CAPTURE_ALWAYS );
 
-    pnss.SetSnapToTracks( frame()->Settings().m_MagneticTracks == CAPTURE_CURSOR_IN_TRACK_TOOL
-                       || frame()->Settings().m_MagneticTracks == CAPTURE_ALWAYS );
+    pnss.SetSnapToTracks(
+            frame()->Settings().m_MagneticTracks == MAGNETIC_OPTIONS::CAPTURE_CURSOR_IN_TRACK_TOOL
+            || frame()->Settings().m_MagneticTracks == MAGNETIC_OPTIONS::CAPTURE_ALWAYS );
 
     if( aItem )
     {
diff --git a/pcbnew/router/pns_tool_base.h b/pcbnew/router/pns_tool_base.h
index 6db5139d4b..c751ab3dd1 100644
--- a/pcbnew/router/pns_tool_base.h
+++ b/pcbnew/router/pns_tool_base.h
@@ -63,7 +63,6 @@ protected:
 
     MSG_PANEL_ITEMS m_panelItems;
 
-    ROUTING_SETTINGS m_savedSettings;     ///< Stores routing settings between router invocations
     SIZES_SETTINGS m_savedSizes;          ///< Stores sizes settings between router invocations
     ITEM* m_startItem;
     int m_startLayer;
diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp
index 4ad11eadd0..dd48306fbc 100644
--- a/pcbnew/router/router_tool.cpp
+++ b/pcbnew/router/router_tool.cpp
@@ -428,13 +428,11 @@ private:
 
 ROUTER_TOOL::~ROUTER_TOOL()
 {
-    m_savedSettings.Save( GetSettings() );
 }
 
 
 bool ROUTER_TOOL::Init()
 {
-    m_savedSettings.Load( GetSettings() );
     return true;
 }
 
@@ -857,8 +855,7 @@ int ROUTER_TOOL::SettingsDialog( const TOOL_EVENT& aEvent )
 {
     DIALOG_PNS_SETTINGS settingsDlg( frame(), m_router->Settings() );
 
-    if( settingsDlg.ShowModal() == wxID_OK )
-        m_savedSettings = m_router->Settings();
+    settingsDlg.ShowModal();
 
     return 0;
 }
@@ -995,7 +992,6 @@ int ROUTER_TOOL::MainLoop( const TOOL_EVENT& aEvent )
     SetContextMenu( nullptr );
 
     // Store routing settings till the next invocation
-    m_savedSettings = m_router->Settings();
     m_savedSizes = m_router->Sizes();
 
     return 0;
diff --git a/pcbnew/sel_layer.cpp b/pcbnew/sel_layer.cpp
index 87f2a4c4f8..81a572c9e2 100644
--- a/pcbnew/sel_layer.cpp
+++ b/pcbnew/sel_layer.cpp
@@ -31,6 +31,7 @@
 #include <class_board.h>
 #include <dialogs/dialog_layer_selection_base.h>
 #include <router/router_tool.h>
+#include <settings/color_settings.h>
 
 
 // Column position by function:
@@ -63,7 +64,7 @@ protected:
     // Virtual function
     COLOR4D GetLayerColor( LAYER_NUM aLayer ) const override
     {
-        return m_frame->Settings().Colors().GetLayerColor( aLayer );
+        return m_frame->ColorSettings()->GetColor( aLayer );
     }
 
     // Returns the name of the layer id
diff --git a/pcbnew/specctra_import_export/specctra_export.cpp b/pcbnew/specctra_import_export/specctra_export.cpp
index 49196899a0..37fc7c203a 100644
--- a/pcbnew/specctra_import_export/specctra_export.cpp
+++ b/pcbnew/specctra_import_export/specctra_export.cpp
@@ -53,6 +53,7 @@
 #include <geometry/convex_hull.h>
 #include <convert_basic_shapes_to_polygon.h>
 #include <geometry/geometry_utils.h>
+#include <pcbnew_settings.h>
 
 #include "specctra.h"
 
diff --git a/pcbnew/specctra_import_export/specctra_import.cpp b/pcbnew/specctra_import_export/specctra_import.cpp
index 81bf7b9bed..635a5eda02 100644
--- a/pcbnew/specctra_import_export/specctra_import.cpp
+++ b/pcbnew/specctra_import_export/specctra_import.cpp
@@ -46,6 +46,7 @@
 #include <view/view.h>
 #include "specctra.h"
 #include <math/util.h>      // for KiROUND
+#include <pcbnew_settings.h>
 
 using namespace DSN;
 
diff --git a/pcbnew/swig/pcbnew_action_plugins.cpp b/pcbnew/swig/pcbnew_action_plugins.cpp
index 8c5c4fbe2c..faf71b64bf 100644
--- a/pcbnew/swig/pcbnew_action_plugins.cpp
+++ b/pcbnew/swig/pcbnew_action_plugins.cpp
@@ -37,6 +37,7 @@
 #include <macros.h>
 #include <menus_helpers.h>
 #include <pcbnew_id.h>
+#include <pcbnew_settings.h>
 #include <python_scripting.h>
 #include <tool/action_menu.h>
 #include <tool/action_toolbar.h>
@@ -422,47 +423,45 @@ void PCB_EDIT_FRAME::AddActionPluginTools()
 }
 
 
-void PCB_EDIT_FRAME::SetActionPluginSettings( const std::vector< std::pair<wxString, wxString> >& aPluginSettings )
+void PCB_EDIT_FRAME::SetActionPluginSettings( const std::vector<wxString>& aPluginSettings )
 {
-    m_configSettings.m_pluginSettings = aPluginSettings;
+    m_Settings->m_VisibleActionPlugins = aPluginSettings;
 }
 
 
-std::vector< std::pair<wxString, wxString> > PCB_EDIT_FRAME::GetActionPluginSettings()
+std::vector<wxString> PCB_EDIT_FRAME::GetActionPluginSettings()
 {
-    return m_configSettings.m_pluginSettings;
+    return m_Settings->m_VisibleActionPlugins;
 }
 
 
 std::vector<ACTION_PLUGIN*> PCB_EDIT_FRAME::GetOrderedActionPlugins()
 {
+    std::vector<ACTION_PLUGIN*> plugins;
     std::vector<ACTION_PLUGIN*> orderedPlugins;
-    const auto& pluginSettings = GetActionPluginSettings();
+
+    for( int i = 0; i < ACTION_PLUGINS::GetActionsCount(); i++ )
+        plugins.push_back( ACTION_PLUGINS::GetAction( i ) );
 
     // First add plugins that have entries in settings
-    for( size_t ii = 0; ii < pluginSettings.size(); ii++ )
+    for( auto visble_plugin : GetActionPluginSettings() )
     {
-        for( int jj = 0; jj < ACTION_PLUGINS::GetActionsCount(); jj++ )
+        auto loc = std::find_if( plugins.begin(), plugins.end(),
+                [visble_plugin] ( ACTION_PLUGIN* plugin )
+                {
+                    return plugin->GetPluginPath().ToStdString() == visble_plugin;
+                } );
+
+        if( loc != plugins.end() )
         {
-            if( ACTION_PLUGINS::GetAction( jj )->GetPluginPath() == pluginSettings[ii].first )
-                orderedPlugins.push_back( ACTION_PLUGINS::GetAction( jj ) );
+            orderedPlugins.push_back( *loc );
+            plugins.erase( loc );
         }
     }
 
     // Now append new plugins that have not been configured yet
-    for( int ii = 0; ii < ACTION_PLUGINS::GetActionsCount(); ii++ )
-    {
-        bool found = false;
-
-        for( size_t jj = 0; jj < orderedPlugins.size(); jj++ )
-        {
-            if( ACTION_PLUGINS::GetAction( ii ) == orderedPlugins[jj] )
-                found = true;
-        }
-
-        if ( !found )
-            orderedPlugins.push_back( ACTION_PLUGINS::GetAction( ii ) );
-    }
+    for( auto remaining_plugin : plugins )
+        orderedPlugins.push_back( remaining_plugin );
 
     return orderedPlugins;
 }
@@ -470,12 +469,12 @@ std::vector<ACTION_PLUGIN*> PCB_EDIT_FRAME::GetOrderedActionPlugins()
 
 bool PCB_EDIT_FRAME::GetActionPluginButtonVisible( const wxString& aPluginPath, bool aPluginDefault )
 {
-    auto& settings = m_configSettings.m_pluginSettings;
+    auto& settings = m_Settings->m_VisibleActionPlugins;
 
-    for(const auto& entry : settings )
+    for( const auto& entry : settings )
     {
-        if (entry.first == aPluginPath )
-            return entry.second == wxT( "Visible" );
+        if( entry == aPluginPath.ToStdString() )
+            return true;
     }
 
     // Plugin is not in settings, return default.
diff --git a/pcbnew/toolbars_pcb_editor.cpp b/pcbnew/toolbars_pcb_editor.cpp
index d83bb5ab90..50356afa0c 100644
--- a/pcbnew/toolbars_pcb_editor.cpp
+++ b/pcbnew/toolbars_pcb_editor.cpp
@@ -24,24 +24,27 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <fctsys.h>
-#include <kiface_i.h>
-#include <help_common_strings.h>
-#include <dialog_helpers.h>
-#include <pcb_edit_frame.h>
-#include <confirm.h>
 #include <bitmaps.h>
 #include <class_board.h>
+#include <confirm.h>
+#include <dialog_helpers.h>
+#include <fctsys.h>
+#include <help_common_strings.h>
+#include <kiface_i.h>
+#include <memory>
+#include <pcb_edit_frame.h>
+#include <pcb_layer_box_selector.h>
+#include <pcbnew.h>
+#include <pcbnew_id.h>
+#include <pcbnew_settings.h>
+#include <pgm_base.h>
+#include <settings/color_settings.h>
+#include <settings/common_settings.h>
 #include <tool/action_toolbar.h>
 #include <tool/actions.h>
-#include <pcbnew.h>
-#include <pcb_layer_box_selector.h>
+#include <tools/pcb_actions.h>
 #include <view/view.h>
 #include <wx/wupdlock.h>
-#include <memory>
-#include <pgm_base.h>
-#include <tools/pcb_actions.h>
-#include <pcbnew_id.h>
 
 extern bool IsWxPythonLoaded();
 
@@ -90,8 +93,7 @@ void PCB_EDIT_FRAME::PrepareLayerIndicator( bool aForceRebuild )
     COLOR4D    active_layer_color, top_color, bottom_color, via_color, background_color;
     bool       change = aForceRebuild;
 
-    int requested_scale;
-    Pgm().CommonSettings()->Read( ICON_SCALE_KEY, &requested_scale, 0 );
+    int requested_scale = Pgm().GetCommonSettings()->m_Appearance.icon_scale;
 
     if( m_prevIconVal.previous_requested_scale != requested_scale )
     {
@@ -99,7 +101,7 @@ void PCB_EDIT_FRAME::PrepareLayerIndicator( bool aForceRebuild )
         change = true;
     }
 
-    active_layer_color = Settings().Colors().GetLayerColor( GetActiveLayer() );
+    active_layer_color = ColorSettings()->GetColor( GetActiveLayer() );
 
     if( m_prevIconVal.previous_active_layer_color != active_layer_color )
     {
@@ -107,7 +109,7 @@ void PCB_EDIT_FRAME::PrepareLayerIndicator( bool aForceRebuild )
         change = true;
     }
 
-    top_color = Settings().Colors().GetLayerColor( GetScreen()->m_Route_Layer_TOP );
+    top_color = ColorSettings()->GetColor( GetScreen()->m_Route_Layer_TOP );
 
     if( m_prevIconVal.previous_Route_Layer_TOP_color != top_color )
     {
@@ -115,7 +117,7 @@ void PCB_EDIT_FRAME::PrepareLayerIndicator( bool aForceRebuild )
         change = true;
     }
 
-    bottom_color = Settings().Colors().GetLayerColor( GetScreen()->m_Route_Layer_BOTTOM );
+    bottom_color = ColorSettings()->GetColor( GetScreen()->m_Route_Layer_BOTTOM );
 
     if( m_prevIconVal.previous_Route_Layer_BOTTOM_color != bottom_color )
     {
@@ -124,7 +126,7 @@ void PCB_EDIT_FRAME::PrepareLayerIndicator( bool aForceRebuild )
     }
 
     int via_type = static_cast<int>( GetDesignSettings().m_CurrentViaType );
-    via_color = Settings().Colors().GetItemColor( LAYER_VIAS + via_type );
+    via_color = ColorSettings()->GetColor( LAYER_VIAS + via_type );
 
     if( m_prevIconVal.previous_via_color != via_color )
     {
@@ -132,7 +134,7 @@ void PCB_EDIT_FRAME::PrepareLayerIndicator( bool aForceRebuild )
         change = true;
     }
 
-    background_color = Settings().Colors().GetItemColor( LAYER_PCB_BACKGROUND );
+    background_color = ColorSettings()->GetColor( LAYER_PCB_BACKGROUND );
 
     if( m_prevIconVal.previous_background_color != background_color )
     {
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index e7fcfb527c..26bad4e519 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -28,6 +28,7 @@
 
 #include <pcb_edit_frame.h>
 #include <project.h>
+#include <pcbnew_settings.h>
 #include <id.h>
 #include <confirm.h>
 #include <import_gfx/dialog_import_gfx.h>
diff --git a/pcbnew/tools/edit_tool.cpp b/pcbnew/tools/edit_tool.cpp
index 87872e7e20..25bc62a8e9 100644
--- a/pcbnew/tools/edit_tool.cpp
+++ b/pcbnew/tools/edit_tool.cpp
@@ -33,6 +33,7 @@
 #include <kiway.h>
 #include <footprint_edit_frame.h>
 #include <array_creator.h>
+#include <pcbnew_settings.h>
 #include <status_popup.h>
 #include <tool/tool_manager.h>
 #include <tools/pcb_actions.h>
diff --git a/pcbnew/tools/grid_helper.cpp b/pcbnew/tools/grid_helper.cpp
index 62509798df..a924b3425c 100644
--- a/pcbnew/tools/grid_helper.cpp
+++ b/pcbnew/tools/grid_helper.cpp
@@ -40,6 +40,7 @@ using namespace std::placeholders;
 #include <math/util.h>      // for KiROUND
 #include <math/vector2d.h>
 #include <painter.h>
+#include <pcbnew_settings.h>
 #include <view/view.h>
 #include <view/view_controls.h>
 
@@ -366,7 +367,8 @@ void GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bo
             for( auto pad : mod->Pads() )
             {
                 // Getting pads from the module requires re-checking that the pad is shown
-                if( ( aFrom || m_frame->Settings().m_MagneticPads == CAPTURE_ALWAYS )
+                if( ( aFrom ||
+                      m_frame->Settings().m_MagneticPads == MAGNETIC_OPTIONS::CAPTURE_ALWAYS )
                         && pad->GetBoundingBox().Contains( wxPoint( aRefPos.x, aRefPos.y ) )
                         && view->IsVisible( pad )
                         && ( !isHighContrast || activeLayers.count( pad->GetLayer() ) )
@@ -384,7 +386,7 @@ void GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bo
 
         case PCB_PAD_T:
         {
-            if( aFrom || m_frame->Settings().m_MagneticPads == CAPTURE_ALWAYS )
+            if( aFrom || m_frame->Settings().m_MagneticPads == MAGNETIC_OPTIONS::CAPTURE_ALWAYS )
             {
                 D_PAD* pad = static_cast<D_PAD*>( aItem );
                 addAnchor( pad->GetPosition(), CORNER | SNAPPABLE, pad );
@@ -459,7 +461,7 @@ void GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bo
 
         case PCB_TRACE_T:
         {
-            if( aFrom || m_frame->Settings().m_MagneticTracks == CAPTURE_ALWAYS )
+            if( aFrom || m_frame->Settings().m_MagneticTracks == MAGNETIC_OPTIONS::CAPTURE_ALWAYS )
             {
                 TRACK* track = static_cast<TRACK*>( aItem );
                 VECTOR2I start = track->GetStart();
@@ -481,7 +483,7 @@ void GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bo
 
         case PCB_VIA_T:
         {
-            if( aFrom || m_frame->Settings().m_MagneticTracks == CAPTURE_ALWAYS )
+            if( aFrom || m_frame->Settings().m_MagneticTracks == MAGNETIC_OPTIONS::CAPTURE_ALWAYS )
                 addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem );
 
             break;
diff --git a/pcbnew/tools/pcb_editor_control.cpp b/pcbnew/tools/pcb_editor_control.cpp
index 0af667617a..08e21a2c18 100644
--- a/pcbnew/tools/pcb_editor_control.cpp
+++ b/pcbnew/tools/pcb_editor_control.cpp
@@ -48,6 +48,7 @@
 #include <painter.h>
 #include <pcb_edit_frame.h>
 #include <pcbnew_id.h>
+#include <pcbnew_settings.h>
 #include <project.h>
 #include <tool/tool_manager.h>
 #include <tools/tool_event_utils.h>
diff --git a/pcbnew/tools/pcb_tool_base.cpp b/pcbnew/tools/pcb_tool_base.cpp
index 17ba47f43b..4ed0bfe384 100644
--- a/pcbnew/tools/pcb_tool_base.cpp
+++ b/pcbnew/tools/pcb_tool_base.cpp
@@ -29,6 +29,7 @@
 #include <board_commit.h>
 #include <class_module.h>
 #include <pcb_draw_panel_gal.h>
+#include <pcbnew_settings.h>
 #include "selection_tool.h"
 #include "pcb_actions.h"
 #include "tool_event_utils.h"
diff --git a/pcbnew/tools/pcbnew_control.cpp b/pcbnew/tools/pcbnew_control.cpp
index 0c034266b9..c75ce9d8f8 100644
--- a/pcbnew/tools/pcbnew_control.cpp
+++ b/pcbnew/tools/pcbnew_control.cpp
@@ -48,7 +48,9 @@
 #include <pcb_edit_frame.h>
 #include <pcb_painter.h>
 #include <pcb_screen.h>
+#include <pcbnew_settings.h>
 #include <properties.h>
+#include <settings/color_settings.h>
 #include <tool/tool_manager.h>
 #include <view/view_controls.h>
 #include <functional>
@@ -401,18 +403,18 @@ int PCBNEW_CONTROL::LayerToggle( const TOOL_EVENT& aEvent )
 
 int PCBNEW_CONTROL::LayerAlphaInc( const TOOL_EVENT& aEvent )
 {
-    auto& settings = m_frame->Settings().Colors();
+    auto settings = m_frame->ColorSettings();
 
     LAYER_NUM currentLayer = m_frame->GetActiveLayer();
-    KIGFX::COLOR4D currentColor = settings.GetLayerColor( currentLayer );
+    KIGFX::COLOR4D currentColor = settings->GetColor( currentLayer );
 
     if( currentColor.a <= ALPHA_MAX - ALPHA_STEP )
     {
         currentColor.a += ALPHA_STEP;
-        settings.SetLayerColor( currentLayer, currentColor );
+        settings->SetColor( currentLayer, currentColor );
+        m_frame->GetCanvas()->UpdateColors();
 
         KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
-        view->GetPainter()->GetSettings()->ImportLegacyColors( &settings );
         view->UpdateLayerColor( currentLayer );
 
         wxUpdateUIEvent dummy;
@@ -427,18 +429,18 @@ int PCBNEW_CONTROL::LayerAlphaInc( const TOOL_EVENT& aEvent )
 
 int PCBNEW_CONTROL::LayerAlphaDec( const TOOL_EVENT& aEvent )
 {
-    auto& settings = m_frame->Settings().Colors();
+    auto settings = m_frame->ColorSettings();
 
     LAYER_NUM currentLayer = m_frame->GetActiveLayer();
-    KIGFX::COLOR4D currentColor = settings.GetLayerColor( currentLayer );
+    KIGFX::COLOR4D currentColor = settings->GetColor( currentLayer );
 
     if( currentColor.a >= ALPHA_MIN + ALPHA_STEP )
     {
         currentColor.a -= ALPHA_STEP;
-        settings.SetLayerColor( currentLayer, currentColor );
+        settings->SetColor( currentLayer, currentColor );
+        m_frame->GetCanvas()->UpdateColors();
 
         KIGFX::VIEW* view = m_frame->GetCanvas()->GetView();
-        view->GetPainter()->GetSettings()->ImportLegacyColors( &settings );
         view->UpdateLayerColor( currentLayer );
 
         wxUpdateUIEvent dummy;
diff --git a/pcbnew/undo_redo.cpp b/pcbnew/undo_redo.cpp
index 92796e8d3b..4ed5592093 100644
--- a/pcbnew/undo_redo.cpp
+++ b/pcbnew/undo_redo.cpp
@@ -43,6 +43,7 @@ using namespace std::placeholders;
 #include <class_edge_mod.h>
 #include <origin_viewitem.h>
 #include <connectivity/connectivity_data.h>
+#include <pcbnew_settings.h>
 #include <tool/tool_manager.h>
 #include <tool/actions.h>
 #include <tools/selection_tool.h>
@@ -521,7 +522,7 @@ void PCB_BASE_EDIT_FRAME::PutDataInPreviousState( PICKED_ITEMS_LIST* aList, bool
         case UR_FLIPPED:
         {
             BOARD_ITEM* item = (BOARD_ITEM*) eda_item;
-            item->Flip( aList->m_TransformPoint, m_configSettings.m_FlipLeftRight );
+            item->Flip( aList->m_TransformPoint, m_Settings->m_FlipLeftRight );
             view->Update( item, KIGFX::LAYERS );
             connectivity->Update( item );
         }
diff --git a/pcbnew/zone_settings.cpp b/pcbnew/zone_settings.cpp
index de6ca4a536..7856a1ecb0 100644
--- a/pcbnew/zone_settings.cpp
+++ b/pcbnew/zone_settings.cpp
@@ -35,6 +35,7 @@
 #include <pcbnew.h>
 #include <pcb_base_frame.h>
 #include <class_board.h>
+#include <settings/color_settings.h>
 #include <zones.h>
 
 #include <class_zone.h>
@@ -175,7 +176,7 @@ void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME*
                                      bool aShowCopper, bool aFpEditorMode )
 {
     BOARD* board = aFrame->GetBoard();
-    COLOR4D backgroundColor = aFrame->Settings().Colors().GetLayerColor( LAYER_PCB_BACKGROUND );
+    COLOR4D backgroundColor = aFrame->ColorSettings()->GetColor( LAYER_PCB_BACKGROUND );
     LSET layers = aShowCopper ? LSET::AllCuMask( board->GetCopperLayerCount() )
                               : LSET::AllNonCuMask();
 
@@ -196,7 +197,7 @@ void ZONE_SETTINGS::SetupLayersList( wxDataViewListCtrl* aList, PCB_BASE_FRAME*
         // wxCOL_WIDTH_AUTOSIZE doesn't work on all platforms, so we calculate width here
         textWidth = std::max( textWidth, GetTextSize( layerName, aList ).x );
 
-        COLOR4D layerColor = aFrame->Settings().Colors().GetLayerColor( layerID );
+        COLOR4D layerColor = aFrame->ColorSettings()->GetColor( layerID );
         auto bitmap = COLOR_SWATCH::MakeBitmap( layerColor, backgroundColor, LAYER_BITMAP_SIZE );
         wxIcon icon;
         icon.CopyFromBitmap( bitmap );
diff --git a/pcbnew/zones.h b/pcbnew/zones.h
index 35f2784368..541ba40592 100644
--- a/pcbnew/zones.h
+++ b/pcbnew/zones.h
@@ -25,15 +25,6 @@
 #ifndef ZONES_H_
 #define ZONES_H_
 
-// keys used to store net sort option in config file :
-#define ZONE_NET_OUTLINES_STYLE_KEY                 wxT( "Zone_Ouline_Hatch_Opt" )
-#define ZONE_NET_SORT_OPTION_KEY                    wxT( "Zone_NetSort_Opt" )
-#define ZONE_NET_FILTER_STRING_KEY                  wxT( "Zone_Filter_Opt" )
-#define ZONE_THERMAL_RELIEF_GAP_STRING_KEY          wxT( "Zone_TH_Gap" )
-#define ZONE_THERMAL_RELIEF_COPPER_WIDTH_STRING_KEY wxT( "Zone_TH_Copper_Width" )
-#define ZONE_CLEARANCE_WIDTH_STRING_KEY             wxT( "Zone_Clearance" )
-#define ZONE_MIN_THICKNESS_WIDTH_STRING_KEY         wxT( "Zone_Thickness" )
-
 // Default values in mils for parameters in ZONE_CONTAINER
 #define ZONE_THERMAL_RELIEF_GAP_MIL 20     // default value for ZONE_SETTINGS::m_ThermalReliefGap
 #define ZONE_THERMAL_RELIEF_COPPER_WIDTH_MIL 20 // default value for ZONE_SETTINGS::m_ThermalReliefCopperBridge
diff --git a/qa/common_tools/CMakeLists.txt b/qa/common_tools/CMakeLists.txt
index c592a48ab6..3373ceb91e 100644
--- a/qa/common_tools/CMakeLists.txt
+++ b/qa/common_tools/CMakeLists.txt
@@ -30,6 +30,9 @@ add_executable( qa_common_tools
     ${CMAKE_SOURCE_DIR}/common/colors.cpp
     ${CMAKE_SOURCE_DIR}/common/observable.cpp
 
+    # Mock Pgm needed for advanced_config in coroutines
+    ${CMAKE_SOURCE_DIR}/qa/qa_utils/mock_pgm.cpp
+
     # The main entry point
     main.cpp
 
@@ -63,4 +66,4 @@ target_include_directories( qa_common_tools PRIVATE
     $<TARGET_PROPERTY:libcontext,INTERFACE_INCLUDE_DIRECTORIES>
 )
 
-kicad_add_utils_executable( qa_common_tools )
+kicad_add_utils_executable( qa_common_tools )
\ No newline at end of file
diff --git a/qa/eeschema/mocks_eeschema.cpp b/qa/eeschema/mocks_eeschema.cpp
index 5bcb48b0c9..d07273d194 100644
--- a/qa/eeschema/mocks_eeschema.cpp
+++ b/qa/eeschema/mocks_eeschema.cpp
@@ -26,6 +26,7 @@
 #include <transform.h>
 
 #include <sch_edit_frame.h>
+#include <settings/settings_manager.h>
 
 // The main sheet of the project
 SCH_SHEET* g_RootSheet = nullptr;
@@ -128,15 +129,11 @@ COLOR4D GetLayerColor( SCH_LAYER_ID aLayer )
     return s_layerColor[layer];
 }
 
-void SetLayerColor( COLOR4D aColor, SCH_LAYER_ID aLayer )
-{
-    // Do not allow non-background layers to be completely white.
-    // This ensures the BW printing recognizes that the colors should be
-    // printed black.
-    if( aColor == COLOR4D::WHITE && aLayer != LAYER_SCHEMATIC_BACKGROUND )
-        aColor.Darken( 0.01 );
 
-    unsigned layer = aLayer;
-    wxASSERT( layer < arrayDim( s_layerColor ) );
-    s_layerColor[layer] = aColor;
+void OnColorsChanged()
+{
+    COLOR_SETTINGS* cs = Pgm().GetSettingsManager().GetColorSettings();
+
+    for( SCH_LAYER_ID layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; ++layer )
+        s_layerColor[layer] = cs->GetColor( layer );
 }
diff --git a/qa/qa_utils/mock_pgm.cpp b/qa/qa_utils/mock_pgm.cpp
new file mode 100644
index 0000000000..11a51d77c1
--- /dev/null
+++ b/qa/qa_utils/mock_pgm.cpp
@@ -0,0 +1,133 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 1992-2020 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 2
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <fctsys.h>
+#include <pgm_base.h>
+#include <kiface_i.h>
+#include <kiway.h>
+#include <kiway_player.h>
+
+
+static struct IFACE : public KIFACE_I
+{
+    // Of course all are overloads, implementations of the KIFACE.
+
+    IFACE( const char* aName, KIWAY::FACE_T aType ) :
+            KIFACE_I( aName, aType )
+    {}
+
+    bool OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) override
+    {
+        return true;
+    }
+
+    void OnKifaceEnd() override {}
+
+    wxWindow* CreateWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) override
+    {
+        assert( false );
+        return nullptr;
+    }
+
+    /**
+     * Function IfaceOrAddress
+     * return a pointer to the requested object.  The safest way to use this
+     * is to retrieve a pointer to a static instance of an interface, similar to
+     * how the KIFACE interface is exported.  But if you know what you are doing
+     * use it to retrieve anything you want.
+     *
+     * @param aDataId identifies which object you want the address of.
+     *
+     * @return void* - and must be cast into the know type.
+     */
+    void* IfaceOrAddress( int aDataId ) override
+    {
+        return NULL;
+    }
+}
+        kiface( "pcb_test_frame", KIWAY::FACE_PCB );
+
+static struct PGM_TEST_FRAME : public PGM_BASE
+{
+    bool OnPgmInit();
+
+    void OnPgmExit()
+    {
+        Kiway.OnKiwayEnd();
+
+        // Destroy everything in PGM_BASE, especially wxSingleInstanceCheckerImpl
+        // earlier than wxApp and earlier than static destruction would.
+        PGM_BASE::Destroy();
+    }
+
+    void MacOpenFile( const wxString& aFileName )   override
+    {
+        wxFileName filename( aFileName );
+
+        if( filename.FileExists() )
+        {
+#if 0
+            // this pulls in EDA_DRAW_FRAME type info, which we don't want in
+            // the single_top link image.
+            KIWAY_PLAYER* frame = dynamic_cast<KIWAY_PLAYER*>( App().GetTopWindow() );
+#else
+            KIWAY_PLAYER* frame = (KIWAY_PLAYER*) App().GetTopWindow();
+#endif
+
+            if( frame )
+                frame->OpenProjectFiles( std::vector<wxString>( 1, aFileName ) );
+        }
+    }
+}
+        program;
+
+PGM_BASE& Pgm()
+{
+    return program;
+}
+
+
+// Similar to PGM_BASE& Pgm(), but return nullptr when a *.ki_face
+// is run from a python script, mot from a Kicad application
+PGM_BASE* PgmOrNull()
+{
+    return &program;
+}
+
+
+KIFACE_I& Kiface()
+{
+    return kiface;
+}
+
+
+class MOCK_PLAYER : public KIWAY_PLAYER
+{
+public:
+    MOCK_PLAYER( KIWAY *aKiway ) :
+            KIWAY_PLAYER( aKiway, nullptr, FRAME_SCH, wxT( "Mock" ), wxDefaultPosition,
+            wxDefaultSize, wxDEFAULT_FRAME_STYLE )
+    {}
+
+    ~MOCK_PLAYER();
+};
\ No newline at end of file
diff --git a/scripting/kicadplugins.i b/scripting/kicadplugins.i
index 20650aab6f..4266b316ce 100644
--- a/scripting/kicadplugins.i
+++ b/scripting/kicadplugins.i
@@ -182,7 +182,7 @@ def LoadPlugins(bundlepath=None):
         importlib.invalidate_caches()
 
     kicad_path = os.environ.get('KICAD_PATH')
-    config_path = pcbnew.GetKicadConfigPath()
+    config_path = pcbnew.SETTINGS_MANAGER.GetUserSettingsPath()
     plugin_directories=[]
 
     """