7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-20 18:11:42 +00:00

API: Show API actions alongside SWIG action plugins in preferences

This commit is contained in:
Jon Evans 2024-12-14 18:00:07 -05:00
parent ac73616e7c
commit 9eda526871
20 changed files with 862 additions and 567 deletions

View File

@ -208,6 +208,13 @@ wxString API_PLUGIN::BasePath() const
}
wxString API_PLUGIN::ActionSettingsKey( const PLUGIN_ACTION& aAction ) const
{
return Identifier() + "." + aAction.identifier;
}
std::optional<PLUGIN_ACTION> API_PLUGIN::createActionFromJson( const nlohmann::json& aJson )
{
// TODO move to tl::expected and give user feedback about parse errors

View File

@ -132,6 +132,15 @@ void API_PLUGIN_MANAGER::ReloadPlugins()
}
std::optional<const PLUGIN_ACTION*> API_PLUGIN_MANAGER::GetAction( const wxString& aIdentifier )
{
if( !m_actionsCache.count( aIdentifier ) )
return std::nullopt;
return m_actionsCache.at( aIdentifier );
}
void API_PLUGIN_MANAGER::InvokeAction( const wxString& aIdentifier )
{
if( !m_actionsCache.count( aIdentifier ) )

View File

@ -1365,19 +1365,72 @@ bool EDA_DRAW_FRAME::SaveCanvasImageToFile( const wxString& aFileName,
}
bool EDA_DRAW_FRAME::IsPluginActionButtonVisible( const PLUGIN_ACTION& aAction,
APP_SETTINGS_BASE* aCfg )
{
wxCHECK( aCfg, aAction.show_button );
for( const auto& [identifier, visible] : aCfg->m_Plugins.actions )
{
if( identifier == aAction.identifier )
return visible;
}
return aAction.show_button;
}
std::vector<const PLUGIN_ACTION*> EDA_DRAW_FRAME::GetOrderedPluginActions(
PLUGIN_ACTION_SCOPE aScope, APP_SETTINGS_BASE* aCfg )
{
std::vector<const PLUGIN_ACTION*> actions;
wxCHECK( aCfg, actions );
#ifdef KICAD_IPC_API
API_PLUGIN_MANAGER& mgr = Pgm().GetPluginManager();
std::vector<const PLUGIN_ACTION*> unsorted = mgr.GetActionsForScope( aScope );
std::map<wxString, const PLUGIN_ACTION*> actionMap;
std::set<const PLUGIN_ACTION*> handled;
for( const PLUGIN_ACTION* action : unsorted )
actionMap[action->identifier] = action;
for( const auto& identifier : aCfg->m_Plugins.actions | std::views::keys )
{
if( actionMap.contains( identifier ) )
{
const PLUGIN_ACTION* action = actionMap[ identifier ];
actions.emplace_back( action );
handled.insert( action );
}
}
for( const auto& action : actionMap | std::views::values )
{
if( !handled.contains( action ) )
actions.emplace_back( action );
}
#endif
return actions;
}
void EDA_DRAW_FRAME::addApiPluginTools()
{
#ifdef KICAD_IPC_API
// TODO: Add user control over visibility and order
API_PLUGIN_MANAGER& mgr = Pgm().GetPluginManager();
mgr.ButtonBindings().clear();
std::vector<const PLUGIN_ACTION*> actions = mgr.GetActionsForScope( PluginActionScope() );
std::vector<const PLUGIN_ACTION*> actions =
GetOrderedPluginActions( PluginActionScope(), config() );
for( auto& action : actions )
for( const PLUGIN_ACTION* action : actions )
{
if( !action->show_button )
if( !IsPluginActionButtonVisible( *action, config() ) )
continue;
const wxBitmapBundle& icon = KIPLATFORM::UI::IsDarkTheme() && action->icon_dark.IsOk()

View File

@ -41,6 +41,7 @@ APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaV
m_Printing(),
m_SearchPane(),
m_System(),
m_Plugins(),
m_Window(),
m_appSettingsSchemaVersion( aSchemaVersion )
{
@ -168,6 +169,39 @@ APP_SETTINGS_BASE::APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaV
m_params.emplace_back( new PARAM<bool>( "system.show_import_issues",
&m_System.show_import_issues, true ) );
m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "plugins.actions",
[&]() -> nlohmann::json
{
nlohmann::json js = nlohmann::json::array();
for( const auto& [identifier, visible] : m_Plugins.actions )
js.push_back( nlohmann::json( { { identifier.ToUTF8(), visible } } ) );
return js;
},
[&]( const nlohmann::json& aObj )
{
m_Plugins.actions.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_Plugins.actions.emplace_back( std::make_pair(
wxString( pair.key().c_str(), wxConvUTF8 ), pair.value() ) );
}
}
},
nlohmann::json::array() ) );
m_params.emplace_back( new PARAM<wxString>( "appearance.color_theme",
&m_ColorTheme, COLOR_SETTINGS::COLOR_BUILTIN_DEFAULT ) );

View File

@ -29,6 +29,7 @@
#include <wx/dc.h>
#include <bitmaps.h>
#include <kiplatform/ui.h>
GRID_CELL_ICON_TEXT_RENDERER::GRID_CELL_ICON_TEXT_RENDERER( const std::vector<BITMAPS>& icons,
@ -39,6 +40,14 @@ GRID_CELL_ICON_TEXT_RENDERER::GRID_CELL_ICON_TEXT_RENDERER( const std::vector<BI
}
GRID_CELL_ICON_TEXT_RENDERER::GRID_CELL_ICON_TEXT_RENDERER( const wxBitmapBundle& aIcon,
wxSize aPreferredIconSize ) :
m_icon( aIcon ),
m_iconSize( aPreferredIconSize )
{
}
void GRID_CELL_ICON_TEXT_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC& aDC,
const wxRect& aRect, int aRow, int aCol, bool isSelected )
{
@ -51,17 +60,18 @@ void GRID_CELL_ICON_TEXT_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, w
wxGridCellRenderer::Draw( aGrid, aAttr, aDC, aRect, aRow, aCol, isSelected );
// draw the icon
// note that the set of icons might be smaller than the set of labels if the last
// label is <...>.
int position = m_names.Index( value );
int leftCut = aDC.FromDIP( 4 );
if( position < (int) m_icons.size() && position != wxNOT_FOUND )
if( m_icon.IsOk() )
{
wxBitmapBundle bundle = KiBitmapBundle( m_icons[position] );
wxSize size = m_iconSize == wxDefaultSize
? m_icon.GetPreferredBitmapSizeAtScale( aDC.GetContentScaleFactor() )
: m_iconSize;
double scale = KIPLATFORM::UI::GetPixelScaleFactor( &aGrid );
wxBitmap bitmap = m_icon.GetBitmap( size * scale );
wxBitmap bitmap = bundle.GetBitmap(
bundle.GetPreferredBitmapSizeAtScale( aDC.GetContentScaleFactor() ) );
if( bitmap.IsOk() )
bitmap.SetScaleFactor( scale );
aDC.DrawBitmap( bitmap,
rect.GetLeft() + leftCut,
@ -70,14 +80,35 @@ void GRID_CELL_ICON_TEXT_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, w
leftCut += bitmap.GetLogicalWidth();
}
else // still need a bitmap to fetch the width
else
{
wxBitmapBundle bundle = KiBitmapBundle( m_icons[0] );
// note that the set of icons might be smaller than the set of labels if the last
// label is <...>.
int position = m_names.Index( value );
wxBitmap bitmap = bundle.GetBitmap(
bundle.GetPreferredBitmapSizeAtScale( aDC.GetContentScaleFactor() ) );
if( position < (int) m_icons.size() && position != wxNOT_FOUND )
{
wxBitmapBundle bundle = KiBitmapBundle( m_icons[position] );
leftCut += bitmap.GetLogicalWidth();
wxBitmap bitmap = bundle.GetBitmap(
bundle.GetPreferredBitmapSizeAtScale( aDC.GetContentScaleFactor() ) );
aDC.DrawBitmap( bitmap,
rect.GetLeft() + leftCut,
rect.GetTop() + ( rect.GetHeight() - bitmap.GetLogicalHeight() ) / 2,
true );
leftCut += bitmap.GetLogicalWidth();
}
else // still need a bitmap to fetch the width
{
wxBitmapBundle bundle = KiBitmapBundle( m_icons[0] );
wxBitmap bitmap = bundle.GetBitmap(
bundle.GetPreferredBitmapSizeAtScale( aDC.GetContentScaleFactor() ) );
leftCut += bitmap.GetLogicalWidth();
}
}
leftCut += aDC.FromDIP( 4 );
@ -90,19 +121,34 @@ void GRID_CELL_ICON_TEXT_RENDERER::Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, w
aGrid.DrawTextRectangle( aDC, value, rect, wxALIGN_LEFT, wxALIGN_CENTRE );
}
wxSize GRID_CELL_ICON_TEXT_RENDERER::GetBestSize( wxGrid& grid, wxGridCellAttr& attr, wxDC& dc,
int row, int col )
{
int bmpIdx = ( row < (int) m_icons.size() && row >= 0 ) ? row : 0;
wxBitmapBundle bundle = KiBitmapBundle( m_icons[bmpIdx] );
wxBitmap bitmap;
wxSize bitmapSize;
wxBitmap bitmap =
bundle.GetBitmap( bundle.GetPreferredBitmapSizeAtScale( dc.GetContentScaleFactor() ) );
if( m_icon.IsOk() )
{
bitmapSize = m_iconSize == wxDefaultSize
? m_icon.GetPreferredBitmapSizeAtScale( dc.GetContentScaleFactor() )
: m_iconSize;
}
else
{
int bmpIdx = ( row < (int) m_icons.size() && row >= 0 ) ? row : 0;
wxBitmapBundle bundle = KiBitmapBundle( m_icons[bmpIdx] );
bitmap = bundle.GetBitmap(
bundle.GetPreferredBitmapSizeAtScale( dc.GetContentScaleFactor() ) );
bitmapSize = wxSize( bitmap.GetLogicalWidth(), -1 );
}
wxString text = grid.GetCellValue( row, col );
wxSize size = wxGridCellStringRenderer::DoGetBestSize( attr, dc, text );
size.x += bitmap.GetLogicalWidth() + dc.FromDIP( 8 );
size.x += bitmapSize.x + dc.FromDIP( 8 );
size.y = std::max( size.y, bitmapSize.y + dc.FromDIP( 2 ) );
return size;
}

View File

@ -118,6 +118,8 @@ public:
const std::vector<PLUGIN_ACTION>& Actions() const;
wxString ActionSettingsKey( const PLUGIN_ACTION& aAction ) const;
private:
friend struct API_PLUGIN_CONFIG;

View File

@ -46,6 +46,8 @@ public:
void InvokeAction( const wxString& aIdentifier );
std::optional<const PLUGIN_ACTION*> GetAction( const wxString& aIdentifier );
std::vector<const PLUGIN_ACTION*> GetActionsForScope( PLUGIN_ACTION_SCOPE aScope );
std::map<int, wxString>& ButtonBindings() { return m_buttonBindings; }

View File

@ -512,6 +512,16 @@ public:
virtual PLUGIN_ACTION_SCOPE PluginActionScope() const { return PLUGIN_ACTION_SCOPE::INVALID; }
static bool IsPluginActionButtonVisible( const PLUGIN_ACTION& aAction, APP_SETTINGS_BASE* aCfg );
/**
* Return ordered list of plugin actions for display in the toolbar
* Must be static at the moment because this needs to be called from the preferences dialog,
* which can exist without the frame in question actually being created.
* @param aCfg is the settings to read the plugin ordering from
*/
static std::vector<const PLUGIN_ACTION*> GetOrderedPluginActions( PLUGIN_ACTION_SCOPE aScope,
APP_SETTINGS_BASE* aCfg );
DECLARE_EVENT_TABLE()

View File

@ -158,6 +158,12 @@ public:
bool show_import_issues;
};
struct PLUGINS
{
/// Ordered list of plugin actions mapped to whether or not they are shown in the toolbar
std::vector<std::pair<wxString, bool>> actions;
};
APP_SETTINGS_BASE( const std::string& aFilename, int aSchemaVersion );
virtual ~APP_SETTINGS_BASE() {}
@ -183,6 +189,8 @@ public:
SYSTEM m_System;
PLUGINS m_Plugins;
WINDOW_SETTINGS m_Window;
/// Active color theme name

View File

@ -39,8 +39,20 @@ enum class BITMAPS : unsigned int;
class GRID_CELL_ICON_TEXT_RENDERER : public wxGridCellStringRenderer
{
public:
/**
* Construct a renderer that maps a list of icons from the bitmap system to a list of strings
* @param icons is a list of possible icons to render
* @param names is a list of names to render - must be the same length as icons
*/
GRID_CELL_ICON_TEXT_RENDERER( const std::vector<BITMAPS>& icons, const wxArrayString& names );
/**
* Construct a renderer that renders a single icon next to the cell's value text
* @param aIcon is the icon to render next to the cell's value
*/
GRID_CELL_ICON_TEXT_RENDERER( const wxBitmapBundle& aIcon,
wxSize aPreferredIconSize = wxDefaultSize );
void Draw( wxGrid& aGrid, wxGridCellAttr& aAttr, wxDC& aDC,
const wxRect& aRect, int aRow, int aCol, bool isSelected ) override;
wxSize GetBestSize( wxGrid & grid, wxGridCellAttr & attr, wxDC & dc, int row, int col ) override;
@ -48,6 +60,10 @@ public:
private:
std::vector<BITMAPS> m_icons;
wxArrayString m_names;
// For single-icon mode
wxBitmapBundle m_icon;
wxSize m_iconSize;
};
//---- Grid helpers: custom wxGridCellRenderer that renders just an icon ----------------

View File

@ -53,6 +53,11 @@ public:
virtual wxString GetName() = 0;
/**
* @return the name of the Python class defining the action
*/
virtual wxString GetClassName() = 0;
/**
* @return a description of the action plugin.
*/
@ -212,4 +217,7 @@ private:
static bool m_actionRunning;
};
typedef std::variant<ACTION_PLUGIN*, const PLUGIN_ACTION*> LEGACY_OR_API_PLUGIN;
#endif /* PCBNEW_ACTION_PLUGINS_H */

View File

@ -19,15 +19,19 @@
*/
#include <action_plugin.h>
#include <api/api_plugin.h>
#include <bitmaps.h>
#include <dialog_footprint_wizard_list.h>
#include <grid_tricks.h>
#include <kiface_base.h>
#include <kiplatform/ui.h>
#include <panel_pcbnew_action_plugins.h>
#include <pcb_edit_frame.h>
#include <python/scripting/pcbnew_scripting.h>
#include <pcb_scripting_tool.h>
#include <pcbnew_settings.h>
#include <pgm_base.h>
#include <api/api_plugin_manager.h>
#include <widgets/grid_icon_text_helpers.h>
#include <widgets/paged_dialog.h>
#include <widgets/wx_grid.h>
@ -39,7 +43,7 @@
PANEL_PCBNEW_ACTION_PLUGINS::PANEL_PCBNEW_ACTION_PLUGINS( wxWindow* aParent ) :
PANEL_PCBNEW_ACTION_PLUGINS_BASE( aParent )
{
m_genericIcon = KiBitmap( BITMAPS::puzzle_piece );
m_genericIcon = KiBitmapBundle( BITMAPS::puzzle_piece );
m_grid->PushEventHandler( new GRID_TRICKS( m_grid ) );
m_grid->SetUseNativeColLabels();
@ -118,10 +122,9 @@ void PANEL_PCBNEW_ACTION_PLUGINS::SwapRows( int aRowA, int aRowB )
{
m_grid->Freeze();
// Swap all columns except icon
wxString tempStr;
for( int column = 1; column < m_grid->GetNumberCols(); column++ )
for( int column = 0; column < m_grid->GetNumberCols(); column++ )
{
tempStr = m_grid->GetCellValue( aRowA, column );
m_grid->SetCellValue( aRowA, column, m_grid->GetCellValue( aRowB, column ) );
@ -129,9 +132,10 @@ void PANEL_PCBNEW_ACTION_PLUGINS::SwapRows( int aRowA, int aRowB )
}
// Swap icon column renderers
auto cellRenderer = m_grid->GetCellRenderer( aRowA, COLUMN_ICON );
m_grid->SetCellRenderer( aRowA, COLUMN_ICON, m_grid->GetCellRenderer( aRowB, COLUMN_ICON ) );
m_grid->SetCellRenderer( aRowB, COLUMN_ICON, cellRenderer );
auto cellRenderer = m_grid->GetCellRenderer( aRowA, COLUMN_ACTION_NAME );
m_grid->SetCellRenderer( aRowA, COLUMN_ACTION_NAME,
m_grid->GetCellRenderer( aRowB, COLUMN_ACTION_NAME ) );
m_grid->SetCellRenderer( aRowB, COLUMN_ACTION_NAME, cellRenderer );
m_grid->Thaw();
}
@ -149,15 +153,27 @@ bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataFromWindow()
PCBNEW_SETTINGS* settings = dynamic_cast<PCBNEW_SETTINGS*>( Kiface().KifaceSettings() );
wxASSERT( settings );
API_PLUGIN_MANAGER& mgr = Pgm().GetPluginManager();
if( settings )
{
settings->m_VisibleActionPlugins.clear();
settings->m_Plugins.actions.clear();
for( int ii = 0; ii < m_grid->GetNumberRows(); ii++ )
{
settings->m_VisibleActionPlugins.emplace_back( std::make_pair(
m_grid->GetCellValue( ii, COLUMN_PATH ),
m_grid->GetCellValue( ii, COLUMN_VISIBLE ) == wxT( "1" ) ) );
wxString id = m_grid->GetCellValue( ii, COLUMN_SETTINGS_IDENTIFIER );
if( mgr.GetAction( id ) != std::nullopt )
{
settings->m_Plugins.actions.emplace_back( std::make_pair(
id, m_grid->GetCellValue( ii, COLUMN_VISIBLE ) == wxT( "1" ) ) );
}
else
{
settings->m_VisibleActionPlugins.emplace_back( std::make_pair(
id, m_grid->GetCellValue( ii, COLUMN_VISIBLE ) == wxT( "1" ) ) );
}
}
}
@ -171,30 +187,66 @@ bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataToWindow()
m_grid->ClearRows();
const auto& orderedPlugins = PCB_EDIT_FRAME::GetOrderedActionPlugins();
const std::vector<LEGACY_OR_API_PLUGIN>& orderedPlugins =
PCB_EDIT_FRAME::GetOrderedActionPlugins();
m_grid->AppendRows( orderedPlugins.size() );
int size = Pgm().GetCommonSettings()->m_Appearance.toolbar_icon_size;
wxSize iconSize( size, size );
for( size_t row = 0; row < orderedPlugins.size(); row++ )
{
ACTION_PLUGIN* ap = orderedPlugins[row];
if( std::holds_alternative<ACTION_PLUGIN*>( orderedPlugins[row] ) )
{
auto ap = std::get<ACTION_PLUGIN*>( orderedPlugins[row] );
// Icon
m_grid->SetCellRenderer( row, COLUMN_ICON, new GRID_CELL_ICON_RENDERER(
ap->iconBitmap.IsOk() ? ap->iconBitmap : m_genericIcon ) );
// Icon
m_grid->SetCellRenderer( row, COLUMN_ACTION_NAME,
new GRID_CELL_ICON_TEXT_RENDERER( ap->iconBitmap.IsOk()
? wxBitmapBundle( ap->iconBitmap )
: m_genericIcon,
iconSize ) );
m_grid->SetCellValue( row, COLUMN_ACTION_NAME, ap->GetName() );
m_grid->SetCellValue( row, COLUMN_SETTINGS_IDENTIFIER, ap->GetPluginPath() );
// Toolbar button checkbox
m_grid->SetCellRenderer( row, COLUMN_VISIBLE, new wxGridCellBoolRenderer() );
m_grid->SetCellAlignment( row, COLUMN_VISIBLE, wxALIGN_CENTER, wxALIGN_CENTER );
// Toolbar button checkbox
m_grid->SetCellRenderer( row, COLUMN_VISIBLE, new wxGridCellBoolRenderer() );
m_grid->SetCellAlignment( row, COLUMN_VISIBLE, wxALIGN_CENTER, wxALIGN_CENTER );
bool show = PCB_EDIT_FRAME::GetActionPluginButtonVisible( ap->GetPluginPath(),
ap->GetShowToolbarButton() );
bool show = PCB_EDIT_FRAME::GetActionPluginButtonVisible( ap->GetPluginPath(),
ap->GetShowToolbarButton() );
m_grid->SetCellValue( row, COLUMN_VISIBLE, show ? wxT( "1" ) : wxEmptyString );
m_grid->SetCellValue( row, COLUMN_VISIBLE, show ? wxT( "1" ) : wxEmptyString );
m_grid->SetCellValue( row, COLUMN_NAME, ap->GetName() );
m_grid->SetCellValue( row, COLUMN_CATEGORY, ap->GetCategoryName() );
m_grid->SetCellValue( row, COLUMN_DESCRIPTION, ap->GetDescription() );
m_grid->SetCellValue( row, COLUMN_PATH, ap->GetPluginPath() );
m_grid->SetCellValue( row, COLUMN_PLUGIN_NAME, ap->GetClassName() );
m_grid->SetCellValue( row, COLUMN_DESCRIPTION, ap->GetDescription() );
}
else
{
auto action = std::get<const PLUGIN_ACTION*>( orderedPlugins[row] );
const wxBitmapBundle& icon = KIPLATFORM::UI::IsDarkTheme() && action->icon_dark.IsOk()
? action->icon_dark
: action->icon_light;
// Icon
m_grid->SetCellRenderer( row, COLUMN_ACTION_NAME, new GRID_CELL_ICON_TEXT_RENDERER(
icon.IsOk() ? icon : m_genericIcon, iconSize ) );
m_grid->SetCellValue( row, COLUMN_ACTION_NAME, action->name );
m_grid->SetCellValue( row, COLUMN_SETTINGS_IDENTIFIER, action->identifier );
// Toolbar button checkbox
m_grid->SetCellRenderer( row, COLUMN_VISIBLE, new wxGridCellBoolRenderer() );
m_grid->SetCellAlignment( row, COLUMN_VISIBLE, wxALIGN_CENTER, wxALIGN_CENTER );
bool show = PCB_EDIT_FRAME::GetActionPluginButtonVisible( action->identifier,
action->show_button );
m_grid->SetCellValue( row, COLUMN_VISIBLE, show ? wxT( "1" ) : wxEmptyString );
m_grid->SetCellValue( row, COLUMN_PLUGIN_NAME, action->plugin.Name() );
m_grid->SetCellValue( row, COLUMN_DESCRIPTION, action->description );
}
}
for( int col = 0; col < m_grid->GetNumberCols(); col++ )
@ -209,6 +261,8 @@ bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataToWindow()
}
m_grid->AutoSizeRows();
m_grid->AutoSizeColumns();
m_grid->HideCol( COLUMN_SETTINGS_IDENTIFIER );
m_grid->Thaw();

View File

@ -63,15 +63,14 @@ private:
enum GRID_COLUMNS
{
COLUMN_ICON,
COLUMN_ACTION_NAME,
COLUMN_VISIBLE,
COLUMN_NAME,
COLUMN_CATEGORY,
COLUMN_PLUGIN_NAME,
COLUMN_DESCRIPTION,
COLUMN_PATH
COLUMN_SETTINGS_IDENTIFIER,
};
wxBitmap m_genericIcon;
wxBitmapBundle m_genericIcon;
void SwapRows( int aRowA, int aRowB );
void SelectRow( int aRow );

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -14,6 +14,9 @@
PANEL_PCBNEW_ACTION_PLUGINS_BASE::PANEL_PCBNEW_ACTION_PLUGINS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
wxBoxSizer* bSizer4;
bSizer4 = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* bPanelSizer;
bPanelSizer = new wxBoxSizer( wxVERTICAL );
@ -23,7 +26,7 @@ PANEL_PCBNEW_ACTION_PLUGINS_BASE::PANEL_PCBNEW_ACTION_PLUGINS_BASE( wxWindow* pa
m_grid = new WX_GRID( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
// Grid
m_grid->CreateGrid( 3, 6 );
m_grid->CreateGrid( 3, 5 );
m_grid->EnableEditing( false );
m_grid->EnableGridLines( true );
m_grid->EnableDragGridSize( false );
@ -33,12 +36,11 @@ PANEL_PCBNEW_ACTION_PLUGINS_BASE::PANEL_PCBNEW_ACTION_PLUGINS_BASE( wxWindow* pa
m_grid->AutoSizeColumns();
m_grid->EnableDragColMove( false );
m_grid->EnableDragColSize( true );
m_grid->SetColLabelValue( 0, _("Icon") );
m_grid->SetColLabelValue( 0, _("Action") );
m_grid->SetColLabelValue( 1, _("Show Button") );
m_grid->SetColLabelValue( 2, _("Name") );
m_grid->SetColLabelValue( 3, _("Category") );
m_grid->SetColLabelValue( 4, _("Description") );
m_grid->SetColLabelValue( 5, _("Path") );
m_grid->SetColLabelValue( 2, _("Plugin") );
m_grid->SetColLabelValue( 3, _("Description") );
m_grid->SetColLabelValue( 4, wxEmptyString );
m_grid->SetColLabelSize( wxGRID_AUTOSIZE );
m_grid->SetColLabelAlignment( wxALIGN_CENTER, wxALIGN_CENTER );
@ -91,9 +93,12 @@ PANEL_PCBNEW_ACTION_PLUGINS_BASE::PANEL_PCBNEW_ACTION_PLUGINS_BASE( wxWindow* pa
bPanelSizer->Add( bButtonsSizer, 0, wxEXPAND|wxLEFT|wxTOP, 5 );
this->SetSizer( bPanelSizer );
bSizer4->Add( bPanelSizer, 1, wxEXPAND, 5 );
this->SetSizer( bSizer4 );
this->Layout();
bPanelSizer->Fit( this );
bSizer4->Fit( this );
// Connect Events
m_grid->Connect( wxEVT_GRID_CELL_LEFT_CLICK, wxGridEventHandler( PANEL_PCBNEW_ACTION_PLUGINS_BASE::OnGridCellClick ), NULL, this );

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!

View File

@ -24,6 +24,7 @@
#include "pcb_base_edit_frame.h"
#include "zones.h"
#include <mail_type.h>
#include <settings/app_settings.h>
class ACTION_PLUGIN;
class PCB_SCREEN;
@ -202,9 +203,9 @@ public:
/**
* Return ordered list of plugins in sequence in which they should appear on toolbar or
* in settings
* in settings. Handles both legacy (SWIG) and API plugins, so returns a heterogenous list.
*/
static std::vector<ACTION_PLUGIN*> GetOrderedActionPlugins();
static std::vector<std::variant<ACTION_PLUGIN*, const PLUGIN_ACTION*>> GetOrderedActionPlugins();
void SaveProjectLocalSettings() override;

View File

@ -171,6 +171,14 @@ wxString PYTHON_ACTION_PLUGIN::GetCategoryName()
}
wxString PYTHON_ACTION_PLUGIN::GetClassName()
{
PyLOCK lock;
return CallRetStrMethod( "GetClassName" );
}
wxString PYTHON_ACTION_PLUGIN::GetName()
{
PyLOCK lock;
@ -496,10 +504,16 @@ void PCB_EDIT_FRAME::buildActionPluginMenus( ACTION_MENU* actionMenu )
void PCB_EDIT_FRAME::AddActionPluginTools()
{
bool need_separator = true;
const std::vector<ACTION_PLUGIN*>& orderedPlugins = GetOrderedActionPlugins();
const std::vector<LEGACY_OR_API_PLUGIN>& orderedPlugins = GetOrderedActionPlugins();
for( ACTION_PLUGIN* ap : orderedPlugins )
for( const auto& entry : orderedPlugins )
{
// API plugins are handled by EDA_BASE_FRAME
if( !std::holds_alternative<ACTION_PLUGIN*>( entry ) )
continue;
ACTION_PLUGIN* ap = std::get<ACTION_PLUGIN*>( entry );
if( GetActionPluginButtonVisible( ap->GetPluginPath(), ap->GetShowToolbarButton() ) )
{
if( need_separator )
@ -529,13 +543,13 @@ void PCB_EDIT_FRAME::AddActionPluginTools()
}
std::vector<ACTION_PLUGIN*> PCB_EDIT_FRAME::GetOrderedActionPlugins()
std::vector<LEGACY_OR_API_PLUGIN> PCB_EDIT_FRAME::GetOrderedActionPlugins()
{
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
PCBNEW_SETTINGS* cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
std::vector<ACTION_PLUGIN*> plugins;
std::vector<ACTION_PLUGIN*> orderedPlugins;
std::vector<LEGACY_OR_API_PLUGIN> orderedPlugins;
for( int i = 0; i < ACTION_PLUGINS::GetActionsCount(); i++ )
plugins.push_back( ACTION_PLUGINS::GetAction( i ) );
@ -560,6 +574,10 @@ std::vector<ACTION_PLUGIN*> PCB_EDIT_FRAME::GetOrderedActionPlugins()
for( auto remaining_plugin : plugins )
orderedPlugins.push_back( remaining_plugin );
// Finally append API plugins
for( const PLUGIN_ACTION* action : GetOrderedPluginActions( PLUGIN_ACTION_SCOPE::PCB, cfg ) )
orderedPlugins.push_back( action );
return orderedPlugins;
}
@ -570,10 +588,16 @@ bool PCB_EDIT_FRAME::GetActionPluginButtonVisible( const wxString& aPluginPath,
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
PCBNEW_SETTINGS* cfg = mgr.GetAppSettings<PCBNEW_SETTINGS>( "pcbnew" );
for( const auto& entry : cfg->m_VisibleActionPlugins )
for( const auto& [path, visible] : cfg->m_VisibleActionPlugins )
{
if( entry.first == aPluginPath )
return entry.second;
if( path == aPluginPath )
return visible;
}
for( const auto& [identifier, visible] : cfg->m_Plugins.actions )
{
if( identifier == aPluginPath )
return visible;
}
// Plugin is not in settings, return default.

View File

@ -43,6 +43,7 @@ public:
PYTHON_ACTION_PLUGIN( PyObject* action );
~PYTHON_ACTION_PLUGIN();
wxString GetCategoryName() override;
wxString GetClassName() override;
wxString GetName() override;
wxString GetDescription() override;
bool GetShowToolbarButton() override;

View File

@ -668,6 +668,9 @@ class ActionPlugin(KiCadPlugin, object):
self.category = "Undefined"
self.description = ""
def GetClassName(self):
return type(self).__name__
def GetName( self ):
return self.name