mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-15 10:43:15 +02:00
Pcbnew: Add ACTION_PLUGINS class. It allows loading python scripts in footprint editor and run them from the Tools/External Plugins menu
This plugin mechanism is enabled only if option -DKICAD_SCRIPTING_ACTION_MENU=ON (it is off by default) It imply -DKICAD_SCRIPTING=0N This is currently for testing purposes only for developers, not yet for users.
This commit is contained in:
parent
df0d102b9c
commit
5ef3e5a15d
@ -63,6 +63,10 @@ option( KICAD_SCRIPTING_WXPYTHON
|
|||||||
"Build wxPython implementation for wx interface building in Python and py.shell (default OFF)."
|
"Build wxPython implementation for wx interface building in Python and py.shell (default OFF)."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
option( KICAD_SCRIPTING_ACTION_MENU
|
||||||
|
"Build a tools menu with registred python plugins: actions plugins (default OFF)."
|
||||||
|
)
|
||||||
|
|
||||||
option( KICAD_USE_SCH_IO_MANAGER
|
option( KICAD_USE_SCH_IO_MANAGER
|
||||||
"Build Eeschema with the I/O manager for handling schematic and symbol library I/O. (default OFF)"
|
"Build Eeschema with the I/O manager for handling schematic and symbol library I/O. (default OFF)"
|
||||||
)
|
)
|
||||||
@ -87,6 +91,12 @@ if ( KICAD_SCRIPTING_MODULES AND NOT KICAD_SCRIPTING )
|
|||||||
set ( KICAD_SCRIPTING ON )
|
set ( KICAD_SCRIPTING ON )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# same with KICAD_SCRIPTING_ACTION_MENUS
|
||||||
|
if ( KICAD_SCRIPTING_ACTION_MENU AND NOT KICAD_SCRIPTING )
|
||||||
|
message(STATUS "Changing KICAD_SCRIPTING to ON as needed by KICAD_SCRIPTING_ACTION_MENU")
|
||||||
|
set ( KICAD_SCRIPTING ON )
|
||||||
|
endif()
|
||||||
|
|
||||||
option( BUILD_GITHUB_PLUGIN "Build the GITHUB_PLUGIN for pcbnew." ON )
|
option( BUILD_GITHUB_PLUGIN "Build the GITHUB_PLUGIN for pcbnew." ON )
|
||||||
|
|
||||||
option( KICAD_SPICE "Build Kicad with internal Spice simulator." OFF )
|
option( KICAD_SPICE "Build Kicad with internal Spice simulator." OFF )
|
||||||
@ -289,6 +299,10 @@ if( KICAD_SCRIPTING_WXPYTHON )
|
|||||||
add_definitions( -DKICAD_SCRIPTING_WXPYTHON )
|
add_definitions( -DKICAD_SCRIPTING_WXPYTHON )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if( KICAD_SCRIPTING_ACTION_MENU )
|
||||||
|
add_definitions( -DKICAD_SCRIPTING_ACTION_MENU )
|
||||||
|
endif()
|
||||||
|
|
||||||
if( KICAD_SPICE )
|
if( KICAD_SPICE )
|
||||||
add_definitions( -DKICAD_SPICE )
|
add_definitions( -DKICAD_SPICE )
|
||||||
endif()
|
endif()
|
||||||
|
@ -117,6 +117,28 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void enableGALSpecificMenus();
|
void enableGALSpecificMenus();
|
||||||
|
|
||||||
|
#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
|
||||||
|
/**
|
||||||
|
* Function initActionPluginMenus
|
||||||
|
* Fill action menu with all registred action plugins
|
||||||
|
*/
|
||||||
|
void initActionPluginMenus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function OnActionPlugin
|
||||||
|
* Launched by the menu when an action is called
|
||||||
|
* @param aEvent sent by wx
|
||||||
|
*/
|
||||||
|
void OnActionPlugin( wxCommandEvent& aEvent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function OnActionPluginRefresh
|
||||||
|
* Refresh plugin list (reload Python plugins)
|
||||||
|
* @param aEvent sent by wx
|
||||||
|
*/
|
||||||
|
void OnActionPluginRefresh( wxCommandEvent& aEvent);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Has meaning only if DKICAD_SCRIPTING_WXPYTHON option is on
|
// Has meaning only if DKICAD_SCRIPTING_WXPYTHON option is on
|
||||||
/**
|
/**
|
||||||
|
@ -274,6 +274,7 @@ set( PCBNEW_CLASS_SRCS
|
|||||||
zones_polygons_test_connections.cpp
|
zones_polygons_test_connections.cpp
|
||||||
zones_test_and_combine_areas.cpp
|
zones_test_and_combine_areas.cpp
|
||||||
class_footprint_wizard.cpp
|
class_footprint_wizard.cpp
|
||||||
|
class_action_plugin.cpp
|
||||||
|
|
||||||
tools/selection_tool.cpp
|
tools/selection_tool.cpp
|
||||||
tools/selection_area.cpp
|
tools/selection_area.cpp
|
||||||
@ -320,6 +321,7 @@ set( PCBNEW_SCRIPTING_PYTHON_HELPERS
|
|||||||
swig/python_scripting.cpp
|
swig/python_scripting.cpp
|
||||||
swig/pcbnew_scripting_helpers.cpp
|
swig/pcbnew_scripting_helpers.cpp
|
||||||
swig/pcbnew_footprint_wizards.cpp
|
swig/pcbnew_footprint_wizards.cpp
|
||||||
|
swig/pcbnew_action_plugins.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if( KICAD_SCRIPTING )
|
if( KICAD_SCRIPTING )
|
||||||
|
155
pcbnew/class_action_plugin.cpp
Normal file
155
pcbnew/class_action_plugin.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file class_action_plugin.cpp
|
||||||
|
* @brief Class ACTION_PLUGIN and ACTION_PLUGINS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "class_action_plugin.h"
|
||||||
|
|
||||||
|
|
||||||
|
ACTION_PLUGIN::~ACTION_PLUGIN()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ACTION_PLUGIN::register_action()
|
||||||
|
{
|
||||||
|
ACTION_PLUGINS::register_action( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<ACTION_PLUGIN*> ACTION_PLUGINS::m_Actions;
|
||||||
|
std::vector<int> ACTION_PLUGINS::m_ActionsMenu;
|
||||||
|
|
||||||
|
|
||||||
|
ACTION_PLUGIN* ACTION_PLUGINS::GetAction( int aIndex )
|
||||||
|
{
|
||||||
|
return m_Actions[aIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ACTION_PLUGIN* ACTION_PLUGINS::GetActionByMenu( int menu )
|
||||||
|
{
|
||||||
|
int max = GetActionsCount();
|
||||||
|
|
||||||
|
for( int i = 0; i<max; i++ )
|
||||||
|
{
|
||||||
|
if( m_ActionsMenu[i] == menu )
|
||||||
|
return m_Actions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ACTION_PLUGINS::SetActionMenu( int aIndex, int idMenu )
|
||||||
|
{
|
||||||
|
m_ActionsMenu[aIndex] = idMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ACTION_PLUGINS::GetActionMenu( int aIndex )
|
||||||
|
{
|
||||||
|
return m_ActionsMenu[aIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ACTION_PLUGIN* ACTION_PLUGINS::GetAction( wxString aName )
|
||||||
|
{
|
||||||
|
int max = GetActionsCount();
|
||||||
|
|
||||||
|
for( int i = 0; i<max; i++ )
|
||||||
|
{
|
||||||
|
ACTION_PLUGIN* action = GetAction( i );
|
||||||
|
|
||||||
|
wxString name = action->GetName();
|
||||||
|
|
||||||
|
if( name.Cmp( aName )==0 )
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ACTION_PLUGINS::GetActionsCount()
|
||||||
|
{
|
||||||
|
return m_Actions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ACTION_PLUGINS::register_action( ACTION_PLUGIN* aAction )
|
||||||
|
{
|
||||||
|
int updatedMenu = 0;
|
||||||
|
|
||||||
|
// Search for this entry do not register twice this action:
|
||||||
|
for( int ii = 0; ii < GetActionsCount(); ii++ )
|
||||||
|
{
|
||||||
|
if( aAction == GetAction( ii ) ) // Already registered
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for a action with the same name, and remove it if found
|
||||||
|
for( int ii = 0; ii < GetActionsCount(); ii++ )
|
||||||
|
{
|
||||||
|
ACTION_PLUGIN* action = GetAction( ii );
|
||||||
|
|
||||||
|
if( action->GetName() == aAction->GetName() )
|
||||||
|
{
|
||||||
|
updatedMenu = GetActionMenu( ii );
|
||||||
|
m_Actions.erase( m_Actions.begin() + ii );
|
||||||
|
m_ActionsMenu.erase( m_ActionsMenu.begin() + ii );
|
||||||
|
|
||||||
|
delete action;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Actions.push_back( aAction );
|
||||||
|
m_ActionsMenu.push_back( updatedMenu );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ACTION_PLUGINS::deregister_object( void* aObject )
|
||||||
|
{
|
||||||
|
int max = GetActionsCount();
|
||||||
|
|
||||||
|
for( int i = 0; i<max; i++ )
|
||||||
|
{
|
||||||
|
ACTION_PLUGIN* action = GetAction( i );
|
||||||
|
|
||||||
|
if( action->GetObject() == aObject )
|
||||||
|
{
|
||||||
|
m_Actions.erase( m_Actions.begin() + i );
|
||||||
|
m_ActionsMenu.erase( m_ActionsMenu.begin() + i );
|
||||||
|
delete action;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
173
pcbnew/class_action_plugin.h
Normal file
173
pcbnew/class_action_plugin.h
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file class_action_plugin.h
|
||||||
|
* @brief Class PCBNEW_ACTION_PLUGINS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CLASS_ACTION_PLUGIN_H
|
||||||
|
#define CLASS_ACTION_PLUGIN_H
|
||||||
|
#include <vector>
|
||||||
|
#include <wxPcbStruct.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ACTION_PLUGIN
|
||||||
|
* This is the parent class from where any action plugin class must
|
||||||
|
* derive
|
||||||
|
*/
|
||||||
|
class ACTION_PLUGIN
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ACTION_PLUGIN() {}
|
||||||
|
virtual ~ACTION_PLUGIN();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetCategoryName
|
||||||
|
* @return the category name of the action (to be able to group action under the same submenu)
|
||||||
|
*/
|
||||||
|
virtual wxString GetCategoryName() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetName
|
||||||
|
* @return the name of the action
|
||||||
|
*/
|
||||||
|
|
||||||
|
virtual wxString GetName() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetDescription
|
||||||
|
* @return a description of the action plugin
|
||||||
|
*/
|
||||||
|
virtual wxString GetDescription() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetObject
|
||||||
|
* This method gets the pointer to the object from where this action constructs
|
||||||
|
* @return it's a void pointer, as it could be a PyObject or any other
|
||||||
|
*/
|
||||||
|
virtual void* GetObject() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function Run
|
||||||
|
* This method the the action
|
||||||
|
*/
|
||||||
|
virtual void Run() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function register_action
|
||||||
|
* It's the standard method of a "ACTION_PLUGIN" to register itself into
|
||||||
|
* the ACTION_PLUGINS singleton manager
|
||||||
|
*/
|
||||||
|
void register_action();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ACTION_PLUGINS
|
||||||
|
* Mainly static. Storing all plugins informations.
|
||||||
|
*/
|
||||||
|
class ACTION_PLUGINS
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* ACTION_PLUGIN system wide static list
|
||||||
|
*/
|
||||||
|
static std::vector<ACTION_PLUGIN*> m_Actions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* system wide static association between Plugin and menu id
|
||||||
|
*/
|
||||||
|
static std::vector<int> m_ActionsMenu;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function register_action
|
||||||
|
* An action calls this static method when it wants to register itself
|
||||||
|
* into the system actions
|
||||||
|
*
|
||||||
|
* @param aAction is the action plugin to be registered
|
||||||
|
*/
|
||||||
|
static void register_action( ACTION_PLUGIN* aAction );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function deregister_object
|
||||||
|
* Anyone calls this method to deregister an object which builds a action,
|
||||||
|
* it will lookup on the vector calling GetObject until find, then removed
|
||||||
|
* and deleted
|
||||||
|
*
|
||||||
|
* @param aObject is the action plugin object to be deregistered
|
||||||
|
*/
|
||||||
|
static bool deregister_object( void* aObject );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetAction
|
||||||
|
* @param aName is the action plugin name
|
||||||
|
* @return a action object by it's name or NULL if it isn't available.
|
||||||
|
*/
|
||||||
|
static ACTION_PLUGIN* GetAction( wxString aName );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function SetActionMenu
|
||||||
|
* Associate a menu id to an action plugin
|
||||||
|
* @param aInded is the action index
|
||||||
|
* @param idMenu is the associated menuitem id
|
||||||
|
*/
|
||||||
|
static void SetActionMenu( int aIndex, int idMenu );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetActionMenu
|
||||||
|
* Provide menu id for a plugin index
|
||||||
|
* @param aIndex is the action index
|
||||||
|
* @return associated menuitem id
|
||||||
|
*/
|
||||||
|
static int GetActionMenu( int aIndex );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetActionByMenu
|
||||||
|
* find action plugin associated to a menu id
|
||||||
|
* @param menu is the menu id (defined with SetActionMenu)
|
||||||
|
* @return the associated ACTION_PLUGIN (or null if not found)
|
||||||
|
*/
|
||||||
|
static ACTION_PLUGIN* GetActionByMenu( int menu );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetAction
|
||||||
|
* @return a action object by it's number or NULL if it isn't available.
|
||||||
|
* @param aIndex is the action index in list
|
||||||
|
*/
|
||||||
|
static ACTION_PLUGIN* GetAction( int aIndex );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function GetActionsCount
|
||||||
|
* @return the number of actions available into the system
|
||||||
|
*/
|
||||||
|
static int GetActionsCount();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* PCBNEW_ACTION_PLUGINS_H */
|
@ -642,6 +642,27 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
|
|||||||
KiBitmap( py_script_xpm ) );
|
KiBitmap( py_script_xpm ) );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
|
||||||
|
toolsMenu->AppendSeparator( );
|
||||||
|
|
||||||
|
wxMenu* submenuActionPluginsMenu = new wxMenu();
|
||||||
|
|
||||||
|
AddMenuItem( toolsMenu, submenuActionPluginsMenu, ID_TOOLBARH_PCB_ACTION_PLUGIN,
|
||||||
|
_( "&External plugins" ),
|
||||||
|
_( "Give access to python action plugin" ),
|
||||||
|
KiBitmap( hammer_xpm ) );
|
||||||
|
|
||||||
|
AddMenuItem( submenuActionPluginsMenu, ID_TOOLBARH_PCB_ACTION_PLUGIN_REFRESH,
|
||||||
|
_( "&Refresh" ),
|
||||||
|
_( "Reload all python plugins and refresh menu" ),
|
||||||
|
KiBitmap( reload_xpm ) );
|
||||||
|
|
||||||
|
submenuActionPluginsMenu->AppendSeparator();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
wxMenu* designRulesMenu = new wxMenu;
|
wxMenu* designRulesMenu = new wxMenu;
|
||||||
|
|
||||||
AddMenuItem( designRulesMenu, ID_MENU_PCB_SHOW_DESIGN_RULES_DIALOG,
|
AddMenuItem( designRulesMenu, ID_MENU_PCB_SHOW_DESIGN_RULES_DIALOG,
|
||||||
|
@ -218,6 +218,11 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
|
|||||||
EVT_TOOL( ID_TOOLBARH_PCB_MODE_TRACKS, PCB_EDIT_FRAME::OnSelectAutoPlaceMode )
|
EVT_TOOL( ID_TOOLBARH_PCB_MODE_TRACKS, PCB_EDIT_FRAME::OnSelectAutoPlaceMode )
|
||||||
EVT_TOOL( ID_TOOLBARH_PCB_FREEROUTE_ACCESS, PCB_EDIT_FRAME::Access_to_External_Tool )
|
EVT_TOOL( ID_TOOLBARH_PCB_FREEROUTE_ACCESS, PCB_EDIT_FRAME::Access_to_External_Tool )
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
|
||||||
|
EVT_TOOL( ID_TOOLBARH_PCB_ACTION_PLUGIN_REFRESH, PCB_EDIT_FRAME::OnActionPluginRefresh )
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined( KICAD_SCRIPTING_WXPYTHON )
|
#if defined( KICAD_SCRIPTING_WXPYTHON )
|
||||||
// has meaning only with KICAD_SCRIPTING_WXPYTHON enabled
|
// has meaning only with KICAD_SCRIPTING_WXPYTHON enabled
|
||||||
EVT_TOOL( ID_TOOLBARH_PCB_SCRIPTING_CONSOLE, PCB_EDIT_FRAME::ScriptingConsoleEnableDisable )
|
EVT_TOOL( ID_TOOLBARH_PCB_SCRIPTING_CONSOLE, PCB_EDIT_FRAME::ScriptingConsoleEnableDisable )
|
||||||
@ -474,6 +479,10 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
|||||||
|
|
||||||
enableGALSpecificMenus();
|
enableGALSpecificMenus();
|
||||||
|
|
||||||
|
#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
|
||||||
|
initActionPluginMenus();
|
||||||
|
#endif
|
||||||
|
|
||||||
// disable Export STEP item if kicad2step does not exist
|
// disable Export STEP item if kicad2step does not exist
|
||||||
wxString strK2S = Pgm().GetExecutablePath();
|
wxString strK2S = Pgm().GetExecutablePath();
|
||||||
#ifdef __WXMAC__
|
#ifdef __WXMAC__
|
||||||
|
@ -280,6 +280,9 @@ enum pcbnew_ids
|
|||||||
ID_TOOLBARH_PCB_FREEROUTE_ACCESS,
|
ID_TOOLBARH_PCB_FREEROUTE_ACCESS,
|
||||||
ID_TOOLBARH_PCB_SCRIPTING_CONSOLE,
|
ID_TOOLBARH_PCB_SCRIPTING_CONSOLE,
|
||||||
|
|
||||||
|
ID_TOOLBARH_PCB_ACTION_PLUGIN,
|
||||||
|
ID_TOOLBARH_PCB_ACTION_PLUGIN_REFRESH,
|
||||||
|
|
||||||
ID_AUX_TOOLBAR_PCB_SELECT_LAYER_PAIR,
|
ID_AUX_TOOLBAR_PCB_SELECT_LAYER_PAIR,
|
||||||
|
|
||||||
ID_PCB_GEN_POS_MODULES_FILE,
|
ID_PCB_GEN_POS_MODULES_FILE,
|
||||||
|
242
pcbnew/swig/pcbnew_action_plugins.cpp
Normal file
242
pcbnew/swig/pcbnew_action_plugins.cpp
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file pcbnew_action_plugins.cpp
|
||||||
|
* @brief Class PCBNEW_PYTHON_ACTION_PLUGINS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pcbnew_action_plugins.h"
|
||||||
|
#include <python_scripting.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <macros.h>
|
||||||
|
#include <pcbnew_id.h>
|
||||||
|
#include <menus_helpers.h>
|
||||||
|
#include <class_drawpanel.h> // m_canvas
|
||||||
|
#include <class_board.h>
|
||||||
|
#include <class_module.h>
|
||||||
|
#include <class_track.h>
|
||||||
|
#include <board_commit.h>
|
||||||
|
#include <kicad_device_context.h>
|
||||||
|
|
||||||
|
PYTHON_ACTION_PLUGIN::PYTHON_ACTION_PLUGIN( PyObject* aAction )
|
||||||
|
{
|
||||||
|
PyLOCK lock;
|
||||||
|
|
||||||
|
this->m_PyAction = aAction;
|
||||||
|
Py_XINCREF( aAction );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PYTHON_ACTION_PLUGIN::~PYTHON_ACTION_PLUGIN()
|
||||||
|
{
|
||||||
|
PyLOCK lock;
|
||||||
|
|
||||||
|
Py_XDECREF( this->m_PyAction );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyObject* PYTHON_ACTION_PLUGIN::CallMethod( const char* aMethod, PyObject* aArglist )
|
||||||
|
{
|
||||||
|
PyLOCK lock;
|
||||||
|
|
||||||
|
PyErr_Clear();
|
||||||
|
// pFunc is a new reference to the desired method
|
||||||
|
PyObject* pFunc = PyObject_GetAttrString( this->m_PyAction, aMethod );
|
||||||
|
|
||||||
|
if( pFunc && PyCallable_Check( pFunc ) )
|
||||||
|
{
|
||||||
|
PyObject* result = PyObject_CallObject( pFunc, aArglist );
|
||||||
|
|
||||||
|
if( PyErr_Occurred() )
|
||||||
|
{
|
||||||
|
wxMessageBox( PyErrStringWithTraceback(),
|
||||||
|
wxT( "Exception on python action plugin code" ),
|
||||||
|
wxICON_ERROR | wxOK );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( result )
|
||||||
|
{
|
||||||
|
Py_XDECREF( pFunc );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf( "method not found, or not callable: %s\n", aMethod );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pFunc )
|
||||||
|
{
|
||||||
|
Py_XDECREF( pFunc );
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString PYTHON_ACTION_PLUGIN::CallRetStrMethod( const char* aMethod, PyObject* aArglist )
|
||||||
|
{
|
||||||
|
wxString ret;
|
||||||
|
PyLOCK lock;
|
||||||
|
|
||||||
|
PyObject* result = CallMethod( aMethod, aArglist );
|
||||||
|
|
||||||
|
if( result )
|
||||||
|
{
|
||||||
|
const char* str_res = PyString_AsString( result );
|
||||||
|
ret = FROM_UTF8( str_res );
|
||||||
|
Py_DECREF( result );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString PYTHON_ACTION_PLUGIN::GetCategoryName()
|
||||||
|
{
|
||||||
|
PyLOCK lock;
|
||||||
|
|
||||||
|
return CallRetStrMethod( "GetCategoryName" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString PYTHON_ACTION_PLUGIN::GetName()
|
||||||
|
{
|
||||||
|
PyLOCK lock;
|
||||||
|
|
||||||
|
return CallRetStrMethod( "GetName" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
wxString PYTHON_ACTION_PLUGIN::GetDescription()
|
||||||
|
{
|
||||||
|
PyLOCK lock;
|
||||||
|
|
||||||
|
return CallRetStrMethod( "GetDescription" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PYTHON_ACTION_PLUGIN::Run()
|
||||||
|
{
|
||||||
|
PyLOCK lock;
|
||||||
|
|
||||||
|
CallMethod( "Run" );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* PYTHON_ACTION_PLUGIN::GetObject()
|
||||||
|
{
|
||||||
|
return (void*) m_PyAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PYTHON_ACTION_PLUGINS::register_action( PyObject* aPyAction )
|
||||||
|
{
|
||||||
|
PYTHON_ACTION_PLUGIN* fw = new PYTHON_ACTION_PLUGIN( aPyAction );
|
||||||
|
|
||||||
|
fw->register_action();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PYTHON_ACTION_PLUGINS::deregister_action( PyObject* aPyAction )
|
||||||
|
{
|
||||||
|
// deregister also destroyes the previously created "PYTHON_ACTION_PLUGIN object"
|
||||||
|
ACTION_PLUGINS::deregister_object( (void*) aPyAction );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(KICAD_SCRIPTING) && defined(KICAD_SCRIPTING_ACTION_MENU)
|
||||||
|
|
||||||
|
void PCB_EDIT_FRAME::OnActionPlugin( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
int id = aEvent.GetId();
|
||||||
|
|
||||||
|
ACTION_PLUGIN* actionPlugin = ACTION_PLUGINS::GetActionByMenu( id );
|
||||||
|
|
||||||
|
if( actionPlugin )
|
||||||
|
{
|
||||||
|
// TODO: Adding recovery point for jobs
|
||||||
|
// BOARD_COMMIT commit( this );
|
||||||
|
// commit.Push( _( "External plugin" ) );
|
||||||
|
|
||||||
|
actionPlugin->Run();
|
||||||
|
|
||||||
|
OnModify();
|
||||||
|
|
||||||
|
if( IsGalCanvasActive() )
|
||||||
|
{
|
||||||
|
UseGalCanvas( GetGalCanvas() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GetScreen()->SetModify();
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PCB_EDIT_FRAME::OnActionPluginRefresh( wxCommandEvent& aEvent )
|
||||||
|
{
|
||||||
|
char cmd[1024];
|
||||||
|
|
||||||
|
snprintf( cmd, sizeof(cmd),
|
||||||
|
"pcbnew.LoadPlugins(\"%s\")", TO_UTF8( PyScriptingPath() ) );
|
||||||
|
|
||||||
|
PyLOCK lock;
|
||||||
|
// ReRun the Python method pcbnew.LoadPlugins (already called when starting Pcbnew)
|
||||||
|
PyRun_SimpleString( cmd );
|
||||||
|
|
||||||
|
initActionPluginMenus();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PCB_EDIT_FRAME::initActionPluginMenus()
|
||||||
|
{
|
||||||
|
wxMenu* actionMenu = GetMenuBar()->FindItem( ID_TOOLBARH_PCB_ACTION_PLUGIN )->GetSubMenu();
|
||||||
|
|
||||||
|
for( int i = 0; i < ACTION_PLUGINS::GetActionsCount(); i++ )
|
||||||
|
{
|
||||||
|
// Init menu only for not already created Items
|
||||||
|
if( ACTION_PLUGINS::GetActionMenu( i ) == 0 )
|
||||||
|
{
|
||||||
|
wxMenuItem* item = AddMenuItem( actionMenu, wxID_ANY,
|
||||||
|
ACTION_PLUGINS::GetAction( i )->GetName(),
|
||||||
|
ACTION_PLUGINS::GetAction( i )->GetDescription(),
|
||||||
|
KiBitmap( hammer_xpm ) );
|
||||||
|
|
||||||
|
ACTION_PLUGINS::SetActionMenu( i, item->GetId() );
|
||||||
|
|
||||||
|
Connect(
|
||||||
|
item->GetId(), wxEVT_COMMAND_MENU_SELECTED,
|
||||||
|
(wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) &
|
||||||
|
PCB_EDIT_FRAME::OnActionPlugin );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete is not handled by plugins system (yet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
62
pcbnew/swig/pcbnew_action_plugins.h
Normal file
62
pcbnew/swig/pcbnew_action_plugins.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 KiCad Developers, see CHANGELOG.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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file pcbnew_action_plugins.h
|
||||||
|
* @brief Class PCBNEW_ACTION_PLUGINS
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PCBNEW_ACTION_PLUGINS_H
|
||||||
|
#define PCBNEW_ACTION_PLUGINS_H
|
||||||
|
#include <Python.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <class_action_plugin.h>
|
||||||
|
|
||||||
|
|
||||||
|
class PYTHON_ACTION_PLUGIN : public ACTION_PLUGIN
|
||||||
|
{
|
||||||
|
PyObject* m_PyAction;
|
||||||
|
PyObject* CallMethod( const char* aMethod,
|
||||||
|
PyObject* aArglist = NULL );
|
||||||
|
wxString CallRetStrMethod( const char* aMethod,
|
||||||
|
PyObject* aArglist = NULL );
|
||||||
|
|
||||||
|
public:
|
||||||
|
PYTHON_ACTION_PLUGIN( PyObject* action );
|
||||||
|
~PYTHON_ACTION_PLUGIN();
|
||||||
|
wxString GetCategoryName() override;
|
||||||
|
wxString GetName() override;
|
||||||
|
wxString GetDescription() override;
|
||||||
|
void Run() override;
|
||||||
|
void* GetObject() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PYTHON_ACTION_PLUGINS
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void register_action( PyObject* aPyAction );
|
||||||
|
static void deregister_action( PyObject* aPyAction );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* PCBNEW_ACTION_PLUGINS_H */
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
%{
|
%{
|
||||||
#include <pcbnew_footprint_wizards.h>
|
#include <pcbnew_footprint_wizards.h>
|
||||||
|
#include <pcbnew_action_plugins.h>
|
||||||
%}
|
%}
|
||||||
|
|
||||||
class PYTHON_FOOTPRINT_WIZARDS
|
class PYTHON_FOOTPRINT_WIZARDS
|
||||||
@ -33,3 +34,11 @@ public:
|
|||||||
static void deregister_wizard( PyObject* wizard );
|
static void deregister_wizard( PyObject* wizard );
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PYTHON_ACTION_PLUGINS
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void register_action( PyObject* wizard );
|
||||||
|
static void deregister_action( PyObject* wizard );
|
||||||
|
|
||||||
|
};
|
||||||
|
@ -208,7 +208,8 @@ class KiCadPlugin:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(self,ActionPlugin):
|
if isinstance(self,ActionPlugin):
|
||||||
pass # register to action plugins in C++
|
PYTHON_ACTION_PLUGINS.register_action(self)
|
||||||
|
return
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -221,7 +222,8 @@ class KiCadPlugin:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(self,ActionPlugin):
|
if isinstance(self,ActionPlugin):
|
||||||
pass # deregister to action plugins in C++
|
PYTHON_ACTION_PLUGINS.deregister_action(self)
|
||||||
|
return
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -560,8 +562,26 @@ class FootprintWizardPlugin(KiCadPlugin, object):
|
|||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
class ActionPlugin(KiCadPlugin):
|
class ActionPlugin(KiCadPlugin, object):
|
||||||
def __init__(self):
|
def __init__( self ):
|
||||||
KiCadPlugin.__init__(self)
|
KiCadPlugin.__init__( self )
|
||||||
|
self.defaults()
|
||||||
|
|
||||||
|
def defaults( self ):
|
||||||
|
self.name = "Undefined Action plugin"
|
||||||
|
self.category = "Undefined"
|
||||||
|
self.description = ""
|
||||||
|
|
||||||
|
def GetName( self ):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def GetCategoryName( self ):
|
||||||
|
return self.category
|
||||||
|
|
||||||
|
def GetDescription( self ):
|
||||||
|
return self.description
|
||||||
|
|
||||||
|
def Run(self):
|
||||||
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user