Eeschema: overhaul storage of BOM plugin settings
CHANGED: BOM generator plugins are no longer loaded by searching all plugin directories; instead a fixed default set of plugins is provided. Also: - Move from sexpr to JSON - Support both full-path and no-path specifications of plugins - Add a Reset to Defaults button to reset the list Fixes https://gitlab.com/kicad/code/kicad/-/issues/7633
This commit is contained in:
parent
c077612163
commit
8d62c73b86
|
@ -23,14 +23,23 @@
|
|||
*/
|
||||
|
||||
#include "bom_plugins.h"
|
||||
#include <paths.h>
|
||||
#include <wx/ffile.h>
|
||||
#include <wx/log.h>
|
||||
|
||||
|
||||
constexpr wxChar BOM_TRACE[] = wxT( "BOM_GENERATORS" );
|
||||
|
||||
|
||||
BOM_GENERATOR_HANDLER::BOM_GENERATOR_HANDLER( const wxString& aFile )
|
||||
: m_file( aFile )
|
||||
{
|
||||
m_isOk = false;
|
||||
|
||||
if( !wxFile::Exists( aFile ) )
|
||||
if( !wxFile::Exists( m_file.GetFullPath() ) )
|
||||
m_file = FindFilePath();
|
||||
|
||||
if( !wxFile::Exists( m_file.GetFullPath() ) )
|
||||
{
|
||||
m_info.Printf( _("Script file:\n%s\nnot found. Script not available."), aFile );
|
||||
return;
|
||||
|
@ -77,6 +86,8 @@ BOM_GENERATOR_HANDLER::BOM_GENERATOR_HANDLER( const wxString& aFile )
|
|||
{
|
||||
m_cmd = m_file.GetFullPath();
|
||||
}
|
||||
|
||||
wxLogTrace( BOM_TRACE, "%s: extracted command line %s", m_name, m_cmd );
|
||||
}
|
||||
|
||||
|
||||
|
@ -147,3 +158,36 @@ wxString BOM_GENERATOR_HANDLER::getOutputExtension( const wxString& aHeader )
|
|||
|
||||
return aHeader.SubString( strstart, strend - 1 );
|
||||
}
|
||||
|
||||
|
||||
wxFileName BOM_GENERATOR_HANDLER::FindFilePath() const
|
||||
{
|
||||
if( m_file.IsAbsolute() && m_file.Exists( wxFILE_EXISTS_REGULAR ) )
|
||||
{
|
||||
wxLogTrace( BOM_TRACE, "%s found directly", m_file.GetFullPath() );
|
||||
return m_file;
|
||||
}
|
||||
|
||||
wxFileName test( PATHS::GetUserPluginsPath(), m_file.GetName(), m_file.GetExt() );
|
||||
|
||||
if( test.Exists( wxFILE_EXISTS_REGULAR ) )
|
||||
{
|
||||
wxLogTrace( BOM_TRACE, "%s found in user plugins path %s", m_file.GetFullName(),
|
||||
PATHS::GetUserPluginsPath() );
|
||||
return test;
|
||||
}
|
||||
|
||||
test = wxFileName( PATHS::GetStockPluginsPath(), m_file.GetName(), m_file.GetExt() );
|
||||
|
||||
if( test.Exists( wxFILE_EXISTS_REGULAR ) )
|
||||
{
|
||||
wxLogTrace( BOM_TRACE, "%s found in stock plugins path %s", m_file.GetFullName(),
|
||||
PATHS::GetStockPluginsPath() );
|
||||
return test;
|
||||
}
|
||||
|
||||
wxLogTrace( BOM_TRACE, "Could not find %s (checked %s, %s)", m_file.GetFullName(),
|
||||
PATHS::GetUserPluginsPath(), PATHS::GetStockPluginsPath() );
|
||||
|
||||
return m_file;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
extern const wxChar BOM_TRACE[];
|
||||
|
||||
/**
|
||||
* Bill of material output generator.
|
||||
*
|
||||
|
@ -78,6 +80,16 @@ public:
|
|||
return m_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the calculated path to the plugin: if the path is already absolute and exists,
|
||||
* just return it. Otherwise if the path is just a filename, look for that file in the user
|
||||
* and system plugin directories and return the first one found. If neither is found, just
|
||||
* return m_file.
|
||||
*
|
||||
* @return the full path to the plugin
|
||||
*/
|
||||
wxFileName FindFilePath() const;
|
||||
|
||||
/**
|
||||
* Return the customisable plugin name.
|
||||
*/
|
||||
|
@ -140,7 +152,7 @@ protected:
|
|||
bool m_isOk;
|
||||
|
||||
///< Path to the plugin
|
||||
const wxFileName m_file;
|
||||
wxFileName m_file;
|
||||
|
||||
///< User customisable name
|
||||
wxString m_name;
|
||||
|
|
|
@ -46,131 +46,18 @@
|
|||
#include <schematic.h>
|
||||
#include <paths.h>
|
||||
|
||||
#include <dialogs/dialog_bom_cfg_lexer.h>
|
||||
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/textdlg.h>
|
||||
|
||||
static constexpr wxChar BOM_TRACE[] = wxT( "BOM_GENERATORS" );
|
||||
|
||||
wxString s_bomHelpInfo =
|
||||
#include <dialog_bom_help_md.h>
|
||||
;
|
||||
|
||||
using namespace T_BOMCFG_T; // for the BOM_CFG_PARSER parser and its keywords
|
||||
|
||||
// BOM "plugins" are not actually plugins. They are external tools
|
||||
// (scripts or executables) called by this dialog.
|
||||
typedef std::vector<BOM_GENERATOR_HANDLER::PTR> BOM_GENERATOR_ARRAY;
|
||||
|
||||
|
||||
/**
|
||||
* Holds data and functions pertinent to parsing a S-expression file
|
||||
*/
|
||||
class BOM_CFG_PARSER : public DIALOG_BOM_CFG_LEXER
|
||||
{
|
||||
BOM_GENERATOR_ARRAY* m_generatorsList;
|
||||
|
||||
public:
|
||||
BOM_CFG_PARSER( BOM_GENERATOR_ARRAY* aGenerators, const char* aData, const wxString& aSource );
|
||||
void Parse();
|
||||
|
||||
private:
|
||||
void parseGenerator();
|
||||
};
|
||||
|
||||
|
||||
BOM_CFG_PARSER::BOM_CFG_PARSER( BOM_GENERATOR_ARRAY* aGenerators, const char* aLine,
|
||||
const wxString& aSource ) :
|
||||
DIALOG_BOM_CFG_LEXER( aLine, aSource )
|
||||
{
|
||||
m_generatorsList = aGenerators;
|
||||
}
|
||||
|
||||
|
||||
void BOM_CFG_PARSER::Parse()
|
||||
{
|
||||
T token;
|
||||
|
||||
while( ( token = NextTok() ) != T_RIGHT )
|
||||
{
|
||||
if( token == T_EOF)
|
||||
break;
|
||||
|
||||
if( token == T_LEFT )
|
||||
token = NextTok();
|
||||
|
||||
if( token == T_plugins )
|
||||
continue;
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_plugin: // Defines a new plugin
|
||||
parseGenerator();
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unexpected( CurText() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BOM_CFG_PARSER::parseGenerator()
|
||||
{
|
||||
NeedSYMBOLorNUMBER();
|
||||
wxString name = FromUTF8();
|
||||
auto plugin = std::make_unique<BOM_GENERATOR_HANDLER>( name );
|
||||
|
||||
T token;
|
||||
|
||||
while( ( token = NextTok() ) != T_RIGHT )
|
||||
{
|
||||
if( token == T_EOF)
|
||||
break;
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_LEFT:
|
||||
break;
|
||||
|
||||
case T_cmd:
|
||||
NeedSYMBOLorNUMBER();
|
||||
|
||||
if( plugin )
|
||||
plugin->SetCommand( FromUTF8() );
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_opts:
|
||||
NeedSYMBOLorNUMBER();
|
||||
|
||||
if( plugin )
|
||||
{
|
||||
wxString option = FromUTF8();
|
||||
|
||||
if( option.StartsWith( "nickname=", &name ) )
|
||||
plugin->SetName( name );
|
||||
else
|
||||
plugin->Options().Add( option );
|
||||
}
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
default:
|
||||
Unexpected( CurText() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( plugin )
|
||||
m_generatorsList->push_back( std::move( plugin ) );
|
||||
}
|
||||
|
||||
|
||||
// The main dialog frame to run scripts to build bom
|
||||
class DIALOG_BOM : public DIALOG_BOM_BASE
|
||||
{
|
||||
|
@ -251,56 +138,44 @@ DIALOG_BOM::DIALOG_BOM( SCH_EDIT_FRAME* parent ) :
|
|||
|
||||
// Now all widgets have the size fixed, call FinishDialogSettings
|
||||
finishDialogSettings();
|
||||
|
||||
m_buttonReset->Bind( wxEVT_BUTTON,
|
||||
[&]( wxCommandEvent& )
|
||||
{
|
||||
EESCHEMA_SETTINGS* cfg = m_parent->eeconfig();
|
||||
|
||||
cfg->m_BomPanel.selected_plugin = wxEmptyString;
|
||||
cfg->m_BomPanel.plugins = cfg->DefaultBomPlugins();
|
||||
|
||||
installGeneratorsList();
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
DIALOG_BOM::~DIALOG_BOM()
|
||||
{
|
||||
if( m_helpWindow )
|
||||
m_helpWindow->Destroy();
|
||||
|
||||
// TODO(JE) maybe unpack this into JSON instead of sexpr
|
||||
EESCHEMA_SETTINGS* cfg = m_parent->eeconfig();
|
||||
|
||||
// Save the plugin descriptions in config.
|
||||
// The config stores only one string, so we save the plugins inside a S-expr:
|
||||
// ( plugins
|
||||
// ( plugin "plugin name 1" (cmd "command line 1") )
|
||||
// ( plugin "plugin name 2" (cmd "command line 2") (opts "option1") (opts "option2") )
|
||||
// ....
|
||||
// )
|
||||
cfg->m_BomPanel.plugins.clear();
|
||||
|
||||
STRING_FORMATTER writer;
|
||||
writer.Print( 0, "(plugins" );
|
||||
|
||||
for( auto& plugin : m_generators )
|
||||
for( const std::unique_ptr<BOM_GENERATOR_HANDLER>& plugin : m_generators )
|
||||
{
|
||||
writer.Print( 1, "(plugin %s (cmd %s)",
|
||||
writer.Quotew( plugin->GetFile().GetFullPath() ).c_str(),
|
||||
writer.Quotew( plugin->GetCommand() ).c_str() );
|
||||
wxString name = plugin->GetName();
|
||||
wxFileName path = plugin->GetFile();
|
||||
|
||||
for( unsigned jj = 0; jj < plugin->Options().GetCount(); jj++ )
|
||||
{
|
||||
writer.Print( 1, "(opts %s)",
|
||||
writer.Quotew( plugin->Options().Item( jj ) ).c_str() );
|
||||
}
|
||||
// handle empty nickname by stripping path
|
||||
if( name.IsEmpty() )
|
||||
name = path.GetName();
|
||||
|
||||
if( !plugin->GetName().IsEmpty() )
|
||||
{
|
||||
wxString option = wxString::Format( "nickname=%s", plugin->GetName() );
|
||||
EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS setting( name, path.GetFullPath() );
|
||||
setting.command = plugin->GetCommand();
|
||||
|
||||
writer.Print( 1, "(opts %s)",
|
||||
writer.Quotew( option ).c_str() );
|
||||
}
|
||||
|
||||
writer.Print( 0, ")" );
|
||||
cfg->m_BomPanel.plugins.emplace_back( setting );
|
||||
}
|
||||
|
||||
writer.Print( 0, ")" );
|
||||
|
||||
wxString list( FROM_UTF8( writer.GetString().c_str() ) );
|
||||
|
||||
auto cfg = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
|
||||
|
||||
cfg->m_BomPanel.plugins = list.ToStdString();
|
||||
cfg->m_BomPanel.selected_plugin = m_lbGenerators->GetStringSelection().ToStdString();
|
||||
}
|
||||
|
||||
|
@ -308,33 +183,36 @@ DIALOG_BOM::~DIALOG_BOM()
|
|||
// Read the initialized plugins in config and fill the list of names
|
||||
void DIALOG_BOM::installGeneratorsList()
|
||||
{
|
||||
auto cfg = static_cast<EESCHEMA_SETTINGS*>( Kiface().KifaceSettings() );
|
||||
EESCHEMA_SETTINGS* cfg = m_parent->eeconfig();
|
||||
|
||||
wxString list = cfg->m_BomPanel.plugins;
|
||||
wxString active_plugin_name = cfg->m_BomPanel.selected_plugin;
|
||||
|
||||
if( !list.IsEmpty() )
|
||||
m_generators.clear();
|
||||
|
||||
for( EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS& setting : cfg->m_BomPanel.plugins )
|
||||
{
|
||||
BOM_CFG_PARSER cfg_parser( &m_generators, TO_UTF8( list ), wxT( "plugins" ) );
|
||||
auto plugin = std::make_unique<BOM_GENERATOR_HANDLER>( setting.path );
|
||||
|
||||
try
|
||||
{
|
||||
cfg_parser.Parse();
|
||||
}
|
||||
catch( const IO_ERROR& )
|
||||
{
|
||||
// wxLogMessage( ioe.What() );
|
||||
}
|
||||
catch( std::runtime_error& e )
|
||||
{
|
||||
DisplayError( nullptr, e.what() );
|
||||
}
|
||||
plugin->SetName( setting.name );
|
||||
|
||||
// Populate list box
|
||||
if( !setting.command.IsEmpty() )
|
||||
plugin->SetCommand( setting.command );
|
||||
|
||||
m_generators.emplace_back( std::move( plugin ) );
|
||||
}
|
||||
|
||||
m_lbGenerators->Clear();
|
||||
|
||||
if( !m_generators.empty() )
|
||||
{
|
||||
for( unsigned ii = 0; ii < m_generators.size(); ii++ )
|
||||
{
|
||||
if( !m_generators[ii]->GetFile().Exists( wxFILE_EXISTS_REGULAR ) )
|
||||
if( !m_generators[ii]->FindFilePath().Exists( wxFILE_EXISTS_REGULAR ) )
|
||||
{
|
||||
wxLogTrace( BOM_TRACE, "BOM plugin %s not found",
|
||||
m_generators[ii]->FindFilePath().GetFullName() );
|
||||
continue;
|
||||
}
|
||||
|
||||
m_lbGenerators->Append( m_generators[ii]->GetName() );
|
||||
|
||||
|
@ -343,53 +221,6 @@ void DIALOG_BOM::installGeneratorsList()
|
|||
}
|
||||
}
|
||||
|
||||
if( m_generators.empty() ) // No plugins found?
|
||||
{
|
||||
// Load plugins from the default locations
|
||||
std::vector<wxString> pluginPaths = {
|
||||
#if defined(__WXGTK__)
|
||||
"/usr/share/kicad/plugins",
|
||||
"/usr/local/share/kicad/plugins",
|
||||
#elif defined(__WXMSW__)
|
||||
wxString::Format( "%s\\scripting\\plugins", Pgm().GetExecutablePath() ),
|
||||
#elif defined(__WXMAC__)
|
||||
wxString::Format( "%s/plugins", PATHS::GetOSXKicadDataDir() ),
|
||||
#endif
|
||||
};
|
||||
|
||||
wxFileName pluginPath;
|
||||
|
||||
for( const auto& path : pluginPaths )
|
||||
{
|
||||
wxDir dir( path );
|
||||
|
||||
if( !dir.IsOpened() )
|
||||
continue;
|
||||
|
||||
pluginPath.AssignDir( dir.GetName() );
|
||||
wxString fileName;
|
||||
bool cont = dir.GetFirst( &fileName, wxFileSelectorDefaultWildcardStr, wxDIR_FILES );
|
||||
|
||||
while( cont )
|
||||
{
|
||||
try
|
||||
{
|
||||
wxLogTrace( BOM_TRACE,"Checking if %s is a BOM generator", fileName );
|
||||
|
||||
if( BOM_GENERATOR_HANDLER::IsValidGenerator( fileName ) )
|
||||
{
|
||||
pluginPath.SetFullName( fileName );
|
||||
addGenerator( pluginPath.GetFullPath() );
|
||||
}
|
||||
}
|
||||
catch( ... ) { /* well, no big deal */ }
|
||||
|
||||
cont = dir.GetNext( &fileName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pluginInit();
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,17 @@ DIALOG_BOM_BASE::DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id, const wxStrin
|
|||
m_staticline = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bMainSizer->Add( m_staticline, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
wxBoxSizer* bSizer8;
|
||||
bSizer8 = new wxBoxSizer( wxHORIZONTAL );
|
||||
|
||||
m_buttonReset = new wxButton( this, wxID_ANY, _("Reset to Defaults"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_buttonReset->SetToolTip( _("Reset the list of BOM generator scripts to the default settings") );
|
||||
|
||||
bSizer8->Add( m_buttonReset, 0, wxALL, 5 );
|
||||
|
||||
|
||||
bSizer8->Add( 0, 0, 1, wxEXPAND, 5 );
|
||||
|
||||
m_sdbSizer = new wxStdDialogButtonSizer();
|
||||
m_sdbSizerOK = new wxButton( this, wxID_OK );
|
||||
m_sdbSizer->AddButton( m_sdbSizerOK );
|
||||
|
@ -118,7 +129,10 @@ DIALOG_BOM_BASE::DIALOG_BOM_BASE( wxWindow* parent, wxWindowID id, const wxStrin
|
|||
m_sdbSizer->AddButton( m_sdbSizerHelp );
|
||||
m_sdbSizer->Realize();
|
||||
|
||||
bMainSizer->Add( m_sdbSizer, 0, wxEXPAND|wxALL, 5 );
|
||||
bSizer8->Add( m_sdbSizer, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
||||
bMainSizer->Add( bSizer8, 0, wxEXPAND, 5 );
|
||||
|
||||
|
||||
this->SetSizer( bMainSizer );
|
||||
|
|
|
@ -920,22 +920,115 @@
|
|||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxALL</property>
|
||||
<property name="flag">wxEXPAND</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">1</property>
|
||||
<property name="No">0</property>
|
||||
<property name="OK">1</property>
|
||||
<property name="Save">0</property>
|
||||
<property name="Yes">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_sdbSizer</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnHelpButtonClick">OnHelp</event>
|
||||
<event name="OnOKButtonClick">OnRunGenerator</event>
|
||||
<property name="name">bSizer8</property>
|
||||
<property name="orient">wxHORIZONTAL</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="wxButton" 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">Reset to Defaults</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_buttonReset</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">Reset the list of BOM generator scripts to the default settings</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>
|
||||
</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">5</property>
|
||||
<property name="flag">wxEXPAND|wxALL</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">1</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"></property>
|
||||
<property name="name">m_sdbSizer</property>
|
||||
<property name="permission">protected</property>
|
||||
<event name="OnHelpButtonClick">OnHelp</event>
|
||||
<event name="OnOKButtonClick">OnRunGenerator</event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
|
|
|
@ -57,6 +57,7 @@ class DIALOG_BOM_BASE : public DIALOG_SHIM
|
|||
wxTextCtrl* m_textCtrlCommand;
|
||||
wxCheckBox* m_checkBoxShowConsole;
|
||||
wxStaticLine* m_staticline;
|
||||
wxButton* m_buttonReset;
|
||||
wxStdDialogButtonSizer* m_sdbSizer;
|
||||
wxButton* m_sdbSizerOK;
|
||||
wxButton* m_sdbSizerCancel;
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <dialogs/dialog_bom_cfg_lexer.h>
|
||||
#include <eeschema_settings.h>
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
#include <symbol_editor_settings.h>
|
||||
|
@ -32,8 +35,22 @@
|
|||
#include <widgets/ui_common.h>
|
||||
#include <default_values.h> // For some default values
|
||||
|
||||
using namespace T_BOMCFG_T; // for the BOM_CFG_PARSER parser and its keywords
|
||||
|
||||
///! Update the schema version whenever a migration is required
|
||||
const int eeschemaSchemaVersion = 0;
|
||||
const int eeschemaSchemaVersion = 1;
|
||||
|
||||
/// Default value for bom.plugins
|
||||
const nlohmann::json defaultBomPlugins = {
|
||||
{
|
||||
{ "name", "bom_csv_grouped_by_value" },
|
||||
{ "path", "bom_csv_grouped_by_value.py" }
|
||||
},
|
||||
{
|
||||
{ "name", "bom_csv_grouped_by_value_with_fp" },
|
||||
{ "path", "bom_csv_grouped_by_value_with_fp.py" }
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
|
||||
|
@ -184,8 +201,18 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
|
|||
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_LAMBDA<nlohmann::json>( "bom.plugins",
|
||||
std::bind( &EESCHEMA_SETTINGS::bomSettingsToJson, this ),
|
||||
[&]( const nlohmann::json& aObj )
|
||||
{
|
||||
if( !aObj.is_array() )
|
||||
return;
|
||||
|
||||
const nlohmann::json& list = aObj.empty() ? defaultBomPlugins : aObj;
|
||||
|
||||
m_BomPanel.plugins = bomSettingsFromJson( list );
|
||||
},
|
||||
defaultBomPlugins ) );
|
||||
|
||||
m_params.emplace_back( new PARAM<bool>( "page_settings.export_paper",
|
||||
&m_PageSettings.export_paper, false ) );
|
||||
|
@ -352,6 +379,15 @@ EESCHEMA_SETTINGS::EESCHEMA_SETTINGS() :
|
|||
m_params.emplace_back( new PARAM<wxString>( "system.last_symbol_lib_dir",
|
||||
&m_lastSymbolLibDir, "" ) );
|
||||
|
||||
|
||||
// Migrations
|
||||
|
||||
registerMigration( 0, 1,
|
||||
[&]() -> bool
|
||||
{
|
||||
// Version 0 to 1: BOM plugin settings moved from sexpr to JSON
|
||||
return migrateBomSettings();
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
|
@ -415,6 +451,8 @@ bool EESCHEMA_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
|
|||
ret &= fromLegacyString( aCfg, "bom_plugin_selected", "bom.selected_plugin" );
|
||||
ret &= fromLegacyString( aCfg, "bom_plugins", "bom.plugins" );
|
||||
|
||||
migrateBomSettings();
|
||||
|
||||
ret &= fromLegacyString( aCfg, "SymbolFieldsShownColumns",
|
||||
"edit_sch_component.visible_columns" );
|
||||
|
||||
|
@ -595,3 +633,191 @@ bool EESCHEMA_SETTINGS::MigrateFromLegacy( wxConfigBase* aCfg )
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Used for parsing legacy-format bom plugin configurations. Only used for migrating into
|
||||
* EESCHEMA_SETTINGS JSON format.
|
||||
*/
|
||||
class BOM_CFG_PARSER : public DIALOG_BOM_CFG_LEXER
|
||||
{
|
||||
std::vector<EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS>* m_pluginList;
|
||||
|
||||
public:
|
||||
BOM_CFG_PARSER( std::vector<EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS>* aPluginList,
|
||||
const char* aData, const wxString& aSource );
|
||||
|
||||
void Parse();
|
||||
|
||||
private:
|
||||
void parseGenerator();
|
||||
};
|
||||
|
||||
|
||||
std::vector<EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS> EESCHEMA_SETTINGS::DefaultBomPlugins()
|
||||
{
|
||||
return bomSettingsFromJson( defaultBomPlugins );
|
||||
}
|
||||
|
||||
|
||||
bool EESCHEMA_SETTINGS::migrateBomSettings()
|
||||
{
|
||||
nlohmann::json::json_pointer ptr = PointerFromString( "bom.plugins" );
|
||||
|
||||
if( !contains( ptr ) )
|
||||
return false;
|
||||
|
||||
wxString list = at( ptr ).get<wxString>();
|
||||
|
||||
BOM_CFG_PARSER cfg_parser( &m_BomPanel.plugins, TO_UTF8( list ), wxT( "plugins" ) );
|
||||
|
||||
try
|
||||
{
|
||||
cfg_parser.Parse();
|
||||
}
|
||||
catch( const IO_ERROR& )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parser will have loaded up our array, let's dump it out to JSON
|
||||
at( ptr ) = bomSettingsToJson();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
nlohmann::json EESCHEMA_SETTINGS::bomSettingsToJson() const
|
||||
{
|
||||
nlohmann::json js = nlohmann::json::array();
|
||||
|
||||
for( const BOM_PLUGIN_SETTINGS& plugin : m_BomPanel.plugins )
|
||||
{
|
||||
nlohmann::json pluginJson;
|
||||
|
||||
pluginJson["name"] = plugin.name.ToUTF8();
|
||||
pluginJson["path"] = plugin.path.ToUTF8();
|
||||
pluginJson["command"] = plugin.command.ToUTF8();
|
||||
|
||||
js.push_back( pluginJson );
|
||||
}
|
||||
|
||||
return js;
|
||||
}
|
||||
|
||||
|
||||
std::vector<EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS> EESCHEMA_SETTINGS::bomSettingsFromJson(
|
||||
const nlohmann::json& aObj )
|
||||
{
|
||||
std::vector<EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS> ret;
|
||||
|
||||
wxASSERT( aObj.is_array() );
|
||||
|
||||
for( const nlohmann::json& entry : aObj )
|
||||
{
|
||||
if( entry.empty() || !entry.is_object() )
|
||||
continue;
|
||||
|
||||
if( !entry.contains( "name" ) || !entry.contains( "path" ) )
|
||||
continue;
|
||||
|
||||
BOM_PLUGIN_SETTINGS plugin( entry.at( "name" ).get<wxString>(),
|
||||
entry.at( "path" ).get<wxString>() );
|
||||
|
||||
if( entry.contains( "command" ) )
|
||||
plugin.command = entry.at( "command" ).get<wxString>();
|
||||
|
||||
ret.emplace_back( plugin );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BOM_CFG_PARSER::BOM_CFG_PARSER( std::vector<EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS>* aPluginList,
|
||||
const char* aLine, const wxString& aSource ) :
|
||||
DIALOG_BOM_CFG_LEXER( aLine, aSource )
|
||||
{
|
||||
wxASSERT( aPluginList );
|
||||
m_pluginList = aPluginList;
|
||||
}
|
||||
|
||||
|
||||
void BOM_CFG_PARSER::Parse()
|
||||
{
|
||||
T token;
|
||||
|
||||
while( ( token = NextTok() ) != T_RIGHT )
|
||||
{
|
||||
if( token == T_EOF)
|
||||
break;
|
||||
|
||||
if( token == T_LEFT )
|
||||
token = NextTok();
|
||||
|
||||
if( token == T_plugins )
|
||||
continue;
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_plugin: // Defines a new plugin
|
||||
parseGenerator();
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unexpected( CurText() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BOM_CFG_PARSER::parseGenerator()
|
||||
{
|
||||
wxString str;
|
||||
EESCHEMA_SETTINGS::BOM_PLUGIN_SETTINGS settings;
|
||||
|
||||
NeedSYMBOLorNUMBER();
|
||||
settings.path = FromUTF8();
|
||||
|
||||
T token;
|
||||
|
||||
while( ( token = NextTok() ) != T_RIGHT )
|
||||
{
|
||||
if( token == T_EOF)
|
||||
break;
|
||||
|
||||
switch( token )
|
||||
{
|
||||
case T_LEFT:
|
||||
break;
|
||||
|
||||
case T_cmd:
|
||||
NeedSYMBOLorNUMBER();
|
||||
|
||||
settings.command = FromUTF8();
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
|
||||
case T_opts:
|
||||
{
|
||||
NeedSYMBOLorNUMBER();
|
||||
|
||||
wxString option = FromUTF8();
|
||||
|
||||
if( option.StartsWith( "nickname=", &str ) )
|
||||
settings.name = str;
|
||||
|
||||
NeedRIGHT();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Unexpected( CurText() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_pluginList->emplace_back( settings );
|
||||
}
|
||||
|
|
|
@ -57,6 +57,20 @@ public:
|
|||
bool align_to_grid;
|
||||
};
|
||||
|
||||
struct BOM_PLUGIN_SETTINGS
|
||||
{
|
||||
BOM_PLUGIN_SETTINGS() = default;
|
||||
|
||||
BOM_PLUGIN_SETTINGS( const wxString& aName, const wxString& aPath ) :
|
||||
name( aName ),
|
||||
path( aPath )
|
||||
{}
|
||||
|
||||
wxString name;
|
||||
wxString path;
|
||||
wxString command;
|
||||
};
|
||||
|
||||
struct DRAWING
|
||||
{
|
||||
int default_bus_thickness;
|
||||
|
@ -126,7 +140,7 @@ public:
|
|||
struct PANEL_BOM
|
||||
{
|
||||
wxString selected_plugin;
|
||||
wxString plugins;
|
||||
std::vector<BOM_PLUGIN_SETTINGS> plugins;
|
||||
};
|
||||
|
||||
struct PANEL_FIELD_EDITOR
|
||||
|
@ -188,6 +202,8 @@ public:
|
|||
|
||||
virtual bool MigrateFromLegacy( wxConfigBase* aLegacyConfig ) override;
|
||||
|
||||
static std::vector<BOM_PLUGIN_SETTINGS> DefaultBomPlugins();
|
||||
|
||||
APPEARANCE m_Appearance;
|
||||
|
||||
AUTOPLACE_FIELDS m_AutoplaceFields;
|
||||
|
@ -223,6 +239,14 @@ public:
|
|||
protected:
|
||||
|
||||
virtual std::string getLegacyFrameName() const override { return "SchematicFrame"; }
|
||||
|
||||
private:
|
||||
|
||||
bool migrateBomSettings();
|
||||
|
||||
nlohmann::json bomSettingsToJson() const;
|
||||
|
||||
static std::vector<BOM_PLUGIN_SETTINGS> bomSettingsFromJson( const nlohmann::json& aObj );
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue