From 1a216f37039916b5e56ccc195aff621d147cfaf1 Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@craftyjon.com>
Date: Thu, 20 Feb 2020 10:59:45 -0500
Subject: [PATCH] Change action plugin settings storage to preserve hidden
 buttons

---
 include/settings/parameters.h                 | 16 ++++++--
 .../dialogs/panel_pcbnew_action_plugins.cpp   | 16 ++++----
 pcbnew/pcb_edit_frame.h                       | 11 ------
 pcbnew/pcbnew_settings.cpp                    | 37 ++++++++++++++++---
 pcbnew/pcbnew_settings.h                      |  6 ++-
 pcbnew/swig/pcbnew_action_plugins.cpp         | 22 +++--------
 6 files changed, 63 insertions(+), 45 deletions(-)

diff --git a/include/settings/parameters.h b/include/settings/parameters.h
index 207586b9f5..c1ebea474c 100644
--- a/include/settings/parameters.h
+++ b/include/settings/parameters.h
@@ -144,17 +144,27 @@ public:
 
         try
         {
-            val = aSettings->Get<ValueType>( m_path );
+            if( std::is_same<ValueType, nlohmann::json>::value )
+                val = aSettings->GetJson( m_path );
+            else
+                val = aSettings->Get<ValueType>( m_path );
         }
         catch( ... )
-        {}
+        {
+        }
 
         m_setter( val );
     }
 
     void Store( JSON_SETTINGS* aSettings) const override
     {
-        aSettings->Set<ValueType>( m_path, m_getter() );
+        try
+        {
+            aSettings->Set<ValueType>( m_path, m_getter() );
+        }
+        catch( ... )
+        {
+        }
     }
 
     ValueType GetDefault() const
diff --git a/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp b/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp
index 77954b8792..8178cc7353 100644
--- a/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp
+++ b/pcbnew/dialogs/panel_pcbnew_action_plugins.cpp
@@ -18,7 +18,9 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <kiface_i.h>
 #include <pcb_edit_frame.h>
+#include <pcbnew_settings.h>
 #include <panel_pcbnew_action_plugins.h>
 #include <widgets/paged_dialog.h>
 #include <widgets/grid_icon_text_helpers.h>
@@ -136,17 +138,15 @@ void PANEL_PCBNEW_ACTION_PLUGINS::OnReloadButtonClick( wxCommandEvent& event )
 
 bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataFromWindow()
 {
-    std::vector<wxString> pluginSettings;
+    auto settings = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() );
+    wxASSERT( settings );
 
-    pluginSettings.reserve( m_grid->GetNumberRows() );
+    settings->m_VisibleActionPlugins.clear();
 
     for( int ii = 0; ii < m_grid->GetNumberRows(); ii++ )
-    {
-        if( m_grid->GetCellValue( ii, COLUMN_VISIBLE ) == wxT( "1" ) )
-            pluginSettings.emplace_back( m_grid->GetCellValue( ii, COLUMN_PATH ) );
-    }
-
-    m_frame->SetActionPluginSettings( pluginSettings );
+        settings->m_VisibleActionPlugins.emplace_back( std::make_pair(
+                m_grid->GetCellValue( ii, COLUMN_PATH ),
+                m_grid->GetCellValue( ii, COLUMN_VISIBLE ) == wxT( "1" ) ) );
 
     return true;
 }
diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h
index e5054a9107..0765406240 100644
--- a/pcbnew/pcb_edit_frame.h
+++ b/pcbnew/pcb_edit_frame.h
@@ -369,17 +369,6 @@ public:
 
 #if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
 
-    /**
-     * Set a set of plugins that have visible buttons on toolbar
-     * Plugins are identified by their module path
-     */
-    void SetActionPluginSettings( const std::vector<wxString>& aPluginsWithButtons );
-
-    /**
-     * Get a set of plugins that have visible buttons on toolbar
-     */
-    std::vector<wxString> GetActionPluginSettings();
-
     /**
      * Function GetActionPluginButtonVisible
      * Returns true if button visibility action plugin setting was set to true
diff --git a/pcbnew/pcbnew_settings.cpp b/pcbnew/pcbnew_settings.cpp
index 37070c7a0d..fdbbcdf451 100644
--- a/pcbnew/pcbnew_settings.cpp
+++ b/pcbnew/pcbnew_settings.cpp
@@ -352,7 +352,33 @@ PCBNEW_SETTINGS::PCBNEW_SETTINGS() : APP_SETTINGS_BASE( "pcbnew", pcbnewSchemaVe
 
 #if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
     m_params.emplace_back(
-            new PARAM_LIST<wxString>( "action_plugins.visible", &m_VisibleActionPlugins, {} ) );
+            new PARAM_LAMBDA<nlohmann::json>( "action_plugins", [&]() -> nlohmann::json {
+                nlohmann::json js = nlohmann::json::array();
+
+                for( const auto& pair : m_VisibleActionPlugins )
+                    js.push_back( nlohmann::json( { { pair.first.ToUTF8(), pair.second } } ) );
+
+                return js;
+            }, [&]( const nlohmann::json& aObj ) {
+                m_VisibleActionPlugins.clear();
+
+                if( !aObj.is_array() )
+                {
+                    return;
+                }
+
+                for( const auto& entry : aObj )
+                {
+                    if( entry.empty() || !entry.is_object() )
+                        continue;
+
+                    for( const auto& pair : entry.items() )
+                    {
+                        m_VisibleActionPlugins.emplace_back( std::make_pair(
+                                wxString( pair.key().c_str(), wxConvUTF8 ), pair.value() ) );
+                    }
+                }
+            }, nlohmann::json::array() ) );
 #endif
 
     addParamsForWindow( &m_FootprintViewer, "footprint_viewer" );
@@ -476,6 +502,7 @@ bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
 
             while( pluginSettingsTokenizer.HasMoreTokens() )
             {
+                nlohmann::json row;
                 wxString plugin = pluginSettingsTokenizer.GetNextToken();
                 wxStringTokenizer pluginTokenizer = wxStringTokenizer( plugin, "=" );
 
@@ -485,14 +512,14 @@ bool PCBNEW_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
                     continue;
                 }
 
-                plugin = pluginTokenizer.GetNextToken();
+                std::string key( pluginTokenizer.GetNextToken().ToUTF8() );
 
-                if( pluginTokenizer.GetNextToken().Cmp( wxT( "Visible" ) ) == 0 )
-                    js.push_back( plugin.ToUTF8() );
+                js.push_back( nlohmann::json( {
+                        { key, pluginTokenizer.GetNextToken().Cmp( wxT( "Visible" ) ) == 0 } } ) );
             }
         }
 
-        ( *this )[PointerFromString( "action_plugins.visible" ) ] = js;
+        ( *this )[PointerFromString( "action_plugins" ) ] = js;
     }
 
     ret &= fromLegacy<int>(    aCfg, "VrmlExportUnit",       "export_vrml.units" );
diff --git a/pcbnew/pcbnew_settings.h b/pcbnew/pcbnew_settings.h
index 41c8391ded..12d0a9698a 100644
--- a/pcbnew/pcbnew_settings.h
+++ b/pcbnew/pcbnew_settings.h
@@ -36,6 +36,10 @@ enum class MAGNETIC_OPTIONS
     CAPTURE_ALWAYS
 };
 
+#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
+typedef std::vector<std::pair<wxString, bool>> ACTION_PLUGIN_SETTINGS_LIST;
+#endif
+
 
 class PCBNEW_SETTINGS : public APP_SETTINGS_BASE
 {
@@ -257,7 +261,7 @@ public:
     PNS::ROUTING_SETTINGS* m_PnsSettings;
 
 #if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
-    std::vector<wxString> m_VisibleActionPlugins;
+    ACTION_PLUGIN_SETTINGS_LIST m_VisibleActionPlugins;
 #endif
 
 protected:
diff --git a/pcbnew/swig/pcbnew_action_plugins.cpp b/pcbnew/swig/pcbnew_action_plugins.cpp
index faf71b64bf..fd60ca2213 100644
--- a/pcbnew/swig/pcbnew_action_plugins.cpp
+++ b/pcbnew/swig/pcbnew_action_plugins.cpp
@@ -423,18 +423,6 @@ void PCB_EDIT_FRAME::AddActionPluginTools()
 }
 
 
-void PCB_EDIT_FRAME::SetActionPluginSettings( const std::vector<wxString>& aPluginSettings )
-{
-    m_Settings->m_VisibleActionPlugins = aPluginSettings;
-}
-
-
-std::vector<wxString> PCB_EDIT_FRAME::GetActionPluginSettings()
-{
-    return m_Settings->m_VisibleActionPlugins;
-}
-
-
 std::vector<ACTION_PLUGIN*> PCB_EDIT_FRAME::GetOrderedActionPlugins()
 {
     std::vector<ACTION_PLUGIN*> plugins;
@@ -444,12 +432,12 @@ std::vector<ACTION_PLUGIN*> PCB_EDIT_FRAME::GetOrderedActionPlugins()
         plugins.push_back( ACTION_PLUGINS::GetAction( i ) );
 
     // First add plugins that have entries in settings
-    for( auto visble_plugin : GetActionPluginSettings() )
+    for( const auto& pair : m_Settings->m_VisibleActionPlugins )
     {
         auto loc = std::find_if( plugins.begin(), plugins.end(),
-                [visble_plugin] ( ACTION_PLUGIN* plugin )
+                [pair] ( ACTION_PLUGIN* plugin )
                 {
-                    return plugin->GetPluginPath().ToStdString() == visble_plugin;
+                    return plugin->GetPluginPath() == pair.first;
                 } );
 
         if( loc != plugins.end() )
@@ -473,8 +461,8 @@ bool PCB_EDIT_FRAME::GetActionPluginButtonVisible( const wxString& aPluginPath,
 
     for( const auto& entry : settings )
     {
-        if( entry == aPluginPath.ToStdString() )
-            return true;
+        if( entry.first == aPluginPath )
+            return entry.second;
     }
 
     // Plugin is not in settings, return default.