Add Python Tool to pcbnew
This commit is contained in:
parent
c7d188a8d0
commit
bf1437899e
|
@ -483,6 +483,7 @@ target_link_libraries( common
|
|||
kimath
|
||||
kiplatform
|
||||
gal
|
||||
scripting
|
||||
pybind11::embed
|
||||
${Boost_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <lockfile.h>
|
||||
#include <menus_helpers.h>
|
||||
#include <pgm_base.h>
|
||||
#include <python_scripting.h>
|
||||
#include <settings/common_settings.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <systemdirsappend.h>
|
||||
|
@ -204,7 +205,6 @@ const wxString PGM_BASE::AskUserForPreferredEditor( const wxString& aDefaultEdit
|
|||
|
||||
bool PGM_BASE::InitPgm( bool aHeadless )
|
||||
{
|
||||
printf("InitPgm()\n");
|
||||
wxFileName pgm_name( App().argv[0] );
|
||||
|
||||
wxInitAllImageHandlers();
|
||||
|
@ -286,6 +286,8 @@ bool PGM_BASE::InitPgm( bool aHeadless )
|
|||
|
||||
ReadPdfBrowserInfos(); // needs GetCommonSettings()
|
||||
|
||||
m_python_scripting = std::make_unique<SCRIPTING>();
|
||||
|
||||
#ifdef __WXMAC__
|
||||
// Always show filters on Open dialog to be able to choose plugin
|
||||
wxSystemOptions::SetOption( wxOSX_FILEDIALOG_ALWAYS_SHOW_TYPES, 1 );
|
||||
|
|
|
@ -47,6 +47,7 @@ class wxWindow;
|
|||
|
||||
class COMMON_SETTINGS;
|
||||
class SETTINGS_MANAGER;
|
||||
class SCRIPTING;
|
||||
|
||||
/**
|
||||
* A small class to handle the list of existing translations.
|
||||
|
@ -305,6 +306,8 @@ protected:
|
|||
|
||||
std::unique_ptr<SETTINGS_MANAGER> m_settings_manager;
|
||||
|
||||
std::unique_ptr<SCRIPTING> m_python_scripting;
|
||||
|
||||
/// prevents multiple instances of a program from being run at the same time.
|
||||
wxSingleInstanceChecker* m_pgm_checker;
|
||||
|
||||
|
|
|
@ -370,6 +370,7 @@ set( PCBNEW_SCRIPTING_PYTHON_HELPERS
|
|||
swig/pcbnew_footprint_wizards.cpp
|
||||
swig/pcbnew_scripting_helpers.cpp
|
||||
swig/pcbnew_scripting.cpp
|
||||
swig/pcb_scripting_tool.cpp
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -18,19 +18,20 @@
|
|||
* 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 <dialog_footprint_wizard_list.h>
|
||||
#include <widgets/paged_dialog.h>
|
||||
#include <widgets/grid_icon_text_helpers.h>
|
||||
#include <bitmaps.h>
|
||||
#include <action_plugin.h>
|
||||
#include <bitmaps.h>
|
||||
#include <dialog_footprint_wizard_list.h>
|
||||
#include <grid_tricks.h>
|
||||
#include <widgets/wx_grid.h>
|
||||
|
||||
#include <kiface_i.h>
|
||||
#include <panel_pcbnew_action_plugins.h>
|
||||
#include <pcb_edit_frame.h>
|
||||
#include <pcbnew_scripting.h>
|
||||
#include <pcbnew_settings.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
#include <widgets/grid_icon_text_helpers.h>
|
||||
#include <widgets/paged_dialog.h>
|
||||
#include <widgets/wx_grid.h>
|
||||
|
||||
#define GRID_CELL_MARGIN 4
|
||||
|
||||
|
@ -138,7 +139,7 @@ void PANEL_PCBNEW_ACTION_PLUGINS::SwapRows( int aRowA, int aRowB )
|
|||
|
||||
void PANEL_PCBNEW_ACTION_PLUGINS::OnReloadButtonClick( wxCommandEvent& event )
|
||||
{
|
||||
m_frame->PythonPluginsReload();
|
||||
m_frame->GetToolManager()->RunAction( PCB_ACTIONS::pluginsReload, true );
|
||||
TransferDataToWindow();
|
||||
}
|
||||
|
||||
|
@ -231,7 +232,7 @@ bool PANEL_PCBNEW_ACTION_PLUGINS::TransferDataToWindow()
|
|||
|
||||
void PANEL_PCBNEW_ACTION_PLUGINS::OnOpenDirectoryButtonClick( wxCommandEvent& event )
|
||||
{
|
||||
m_frame->PythonPluginsShowFolder();
|
||||
m_frame->GetToolManager()->RunAction( PCB_ACTIONS::pluginsShowFolder );
|
||||
}
|
||||
|
||||
void PANEL_PCBNEW_ACTION_PLUGINS::OnShowErrorsButtonClick( wxCommandEvent& event )
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "tools/placement_tool.h"
|
||||
#include "tools/pcb_point_editor.h"
|
||||
#include "tools/pcb_selection_tool.h"
|
||||
#include <swig/pcb_scripting_tool.h>
|
||||
#include <3d_viewer/eda_3d_viewer.h>
|
||||
#include <bitmaps.h>
|
||||
#include <board.h>
|
||||
|
@ -943,6 +944,7 @@ void FOOTPRINT_EDIT_FRAME::setupTools()
|
|||
m_toolManager->RegisterTool( new PCB_VIEWER_TOOLS );
|
||||
m_toolManager->RegisterTool( new GROUP_TOOL );
|
||||
m_toolManager->RegisterTool( new CONVERT_TOOL );
|
||||
m_toolManager->RegisterTool( new SCRIPTING_TOOL );
|
||||
|
||||
m_toolManager->GetTool<PCB_SELECTION_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<EDIT_TOOL>()->SetIsFootprintEditor( true );
|
||||
|
@ -953,6 +955,7 @@ void FOOTPRINT_EDIT_FRAME::setupTools()
|
|||
m_toolManager->GetTool<PCB_PICKER_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<POSITION_RELATIVE_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<GROUP_TOOL>()->SetIsFootprintEditor( true );
|
||||
m_toolManager->GetTool<SCRIPTING_TOOL>()->SetIsFootprintEditor( true );
|
||||
|
||||
m_toolManager->GetTool<PCB_VIEWER_TOOLS>()->SetFootprintFrame( true );
|
||||
m_toolManager->InitTools();
|
||||
|
|
|
@ -647,7 +647,7 @@ void FOOTPRINT_WIZARD_FRAME::PythonPluginsReload()
|
|||
auto brd_frame = static_cast<PCB_EDIT_FRAME*>( Kiway().Player( FRAME_PCB_EDITOR, false ) );
|
||||
|
||||
if( brd_frame )
|
||||
brd_frame->PythonPluginsReload();
|
||||
brd_frame->GetToolManager()->RunAction( PCB_ACTIONS::pluginsReload );
|
||||
else
|
||||
PythonPluginsReloadBase();
|
||||
GetToolManager()->RunAction( PCB_ACTIONS::pluginsReload );
|
||||
}
|
||||
|
|
|
@ -413,21 +413,9 @@ void PCB_EDIT_FRAME::ReCreateMenuBar()
|
|||
submenuActionPlugins->SetTitle( _( "External Plugins" ) );
|
||||
submenuActionPlugins->SetIcon( BITMAPS::puzzle_piece );
|
||||
|
||||
submenuActionPlugins->Add( _( "Refresh Plugins" ),
|
||||
_( "Reload all python plugins and refresh plugin menus" ),
|
||||
ID_TOOLBARH_PCB_ACTION_PLUGIN_REFRESH,
|
||||
BITMAPS::reload );
|
||||
#ifdef __APPLE__
|
||||
submenuActionPlugins->Add( _( "Reveal Plugin Folder in Finder" ),
|
||||
_( "Reveals the plugins folder in a Finder window" ),
|
||||
ID_TOOLBARH_PCB_ACTION_PLUGIN_SHOW_FOLDER,
|
||||
BITMAPS::directory_open );
|
||||
#else
|
||||
submenuActionPlugins->Add( _( "Open Plugin Directory" ),
|
||||
_( "Opens the directory in the default system file manager" ),
|
||||
ID_TOOLBARH_PCB_ACTION_PLUGIN_SHOW_FOLDER,
|
||||
BITMAPS::directory_open );
|
||||
#endif
|
||||
submenuActionPlugins->Add( PCB_ACTIONS::pluginsReload );
|
||||
submenuActionPlugins->Add( PCB_ACTIONS::pluginsShowFolder );
|
||||
|
||||
// Populate the Action Plugin sub-menu: Must be done before Add
|
||||
// Since the object is cloned by Add
|
||||
submenuActionPlugins->AppendSeparator();
|
||||
|
|
|
@ -84,6 +84,7 @@
|
|||
#include <router/router_tool.h>
|
||||
#include <router/length_tuner_tool.h>
|
||||
#include <autorouter/autoplace_tool.h>
|
||||
#include <swig/pcb_scripting_tool.h>
|
||||
#include <gestfich.h>
|
||||
#include <executable_names.h>
|
||||
#include <netlist_reader/board_netlist_updater.h>
|
||||
|
@ -147,9 +148,6 @@ BEGIN_EVENT_TABLE( PCB_EDIT_FRAME, PCB_BASE_FRAME )
|
|||
EVT_CHOICE( ID_AUX_TOOLBAR_PCB_TRACK_WIDTH, PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event )
|
||||
EVT_CHOICE( ID_AUX_TOOLBAR_PCB_VIA_SIZE, PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event )
|
||||
|
||||
EVT_TOOL( ID_TOOLBARH_PCB_ACTION_PLUGIN_REFRESH, PCB_EDIT_FRAME::OnActionPluginRefresh )
|
||||
EVT_TOOL( ID_TOOLBARH_PCB_ACTION_PLUGIN_SHOW_FOLDER, PCB_EDIT_FRAME::OnActionPluginShowFolder )
|
||||
|
||||
// Tracks and vias sizes general options
|
||||
EVT_MENU_RANGE( ID_POPUP_PCB_SELECT_WIDTH_START_RANGE, ID_POPUP_PCB_SELECT_WIDTH_END_RANGE,
|
||||
PCB_EDIT_FRAME::Tracks_and_Vias_Size_Event )
|
||||
|
@ -496,6 +494,7 @@ void PCB_EDIT_FRAME::setupTools()
|
|||
m_toolManager->RegisterTool( new PCB_VIEWER_TOOLS );
|
||||
m_toolManager->RegisterTool( new CONVERT_TOOL );
|
||||
m_toolManager->RegisterTool( new GROUP_TOOL );
|
||||
m_toolManager->RegisterTool( new SCRIPTING_TOOL );
|
||||
m_toolManager->InitTools();
|
||||
|
||||
// Run the selection tool, it is supposed to be always active
|
||||
|
@ -1498,43 +1497,6 @@ void PCB_EDIT_FRAME::RunEeschema()
|
|||
}
|
||||
|
||||
|
||||
void PCB_EDIT_FRAME::PythonPluginsReload()
|
||||
{
|
||||
// Reload Python plugins if they are newer than the already loaded, and load new plugins
|
||||
// Remove all action plugins so that we don't keep references to old versions
|
||||
ACTION_PLUGINS::UnloadAll();
|
||||
|
||||
// Reload plugin list: reload Python plugins if they are newer than the already loaded,
|
||||
// and load new plugins
|
||||
PythonPluginsReloadBase();
|
||||
|
||||
// Action plugins can be modified, therefore the plugins menu must be updated:
|
||||
ReCreateMenuBar();
|
||||
// Recreate top toolbar to add action plugin buttons
|
||||
ReCreateHToolbar();
|
||||
}
|
||||
|
||||
|
||||
void PCB_EDIT_FRAME::PythonPluginsShowFolder()
|
||||
{
|
||||
#ifdef __WXMAC__
|
||||
wxString msg;
|
||||
|
||||
// Quote in case there are spaces in the path.
|
||||
msg.Printf( "open \"%s\"", PyPluginsPath( true ) );
|
||||
|
||||
system( msg.c_str() );
|
||||
#else
|
||||
wxString pypath( PyPluginsPath( true ) );
|
||||
|
||||
// Quote in case there are spaces in the path.
|
||||
AddDelimiterString( pypath );
|
||||
|
||||
wxLaunchDefaultApplication( pypath );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void PCB_EDIT_FRAME::PythonSyncEnvironmentVariables()
|
||||
{
|
||||
const ENV_VAR_MAP& vars = Pgm().GetLocalEnvVariables();
|
||||
|
|
|
@ -93,12 +93,6 @@ public:
|
|||
*/
|
||||
bool IsContentModified() const override;
|
||||
|
||||
/**
|
||||
* Reload the Python plugins if they are newer than the already loaded, and load new
|
||||
* plugins if any.
|
||||
*/
|
||||
void PythonPluginsReload();
|
||||
|
||||
/**
|
||||
* Open the plugins folder in the default system file browser.
|
||||
*/
|
||||
|
|
|
@ -216,26 +216,6 @@ PGM_BASE* PgmOrNull()
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
void PythonPluginsReloadBase()
|
||||
{
|
||||
// Reload plugin list: reload Python plugins if they are newer than the already loaded,
|
||||
// and load new plugins
|
||||
char cmd[1024];
|
||||
|
||||
snprintf( cmd, sizeof( cmd ), "pcbnew.LoadPlugins(\"%s\", \"%s\")", TO_UTF8( PyScriptingPath() ),
|
||||
TO_UTF8( PyScriptingPath( true ) ) );
|
||||
|
||||
PyLOCK lock;
|
||||
|
||||
// ReRun the Python method pcbnew.LoadPlugins (already called when starting Pcbnew)
|
||||
int retv = PyRun_SimpleString( cmd );
|
||||
|
||||
if( retv != 0 )
|
||||
wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, cmd );
|
||||
}
|
||||
|
||||
|
||||
/// The global footprint library table. This is not dynamically allocated because
|
||||
/// in a multiple project environment we must keep its address constant (since it is
|
||||
/// the fallback table for multiple projects).
|
||||
|
|
|
@ -33,14 +33,4 @@
|
|||
#define TEXTS_MAX_WIDTH Mils2iu( 10000 ) ///< Maximum text width in internal units (10 inches)
|
||||
|
||||
|
||||
/**
|
||||
* Helper function PythonPluginsReloadBase
|
||||
* Reload Python plugins if they are newer than
|
||||
* the already loaded, and load new plugins if any
|
||||
* It calls the LoadPlugins(bundlepath) Python method
|
||||
* see kicadplugins.i
|
||||
*/
|
||||
void PythonPluginsReloadBase();
|
||||
|
||||
|
||||
#endif // PCBNEW_H
|
||||
|
|
|
@ -88,8 +88,6 @@ enum pcbnew_ids
|
|||
ID_GEN_EXPORT_FILE_GENCADFORMAT,
|
||||
|
||||
ID_TOOLBARH_PCB_ACTION_PLUGIN,
|
||||
ID_TOOLBARH_PCB_ACTION_PLUGIN_REFRESH,
|
||||
ID_TOOLBARH_PCB_ACTION_PLUGIN_SHOW_FOLDER,
|
||||
|
||||
ID_PCB_GEN_CMP_FILE,
|
||||
ID_PCB_GEN_BOM_FILE_FROM_BOARD,
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 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 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "pcb_scripting_tool.h"
|
||||
|
||||
#include <action_plugin.h>
|
||||
#include <gestfich.h>
|
||||
#include <kiface_ids.h>
|
||||
#include <kiway.h>
|
||||
#include <python_scripting.h>
|
||||
#include <tools/pcb_actions.h>
|
||||
|
||||
#include <pybind11/eval.h>
|
||||
|
||||
#include <Python.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
using initfunc = PyObject* (*)(void);
|
||||
|
||||
SCRIPTING_TOOL::SCRIPTING_TOOL() :
|
||||
PCB_TOOL_BASE( "pcbnew.ScriptingTool" )
|
||||
{}
|
||||
|
||||
|
||||
SCRIPTING_TOOL::~SCRIPTING_TOOL()
|
||||
{}
|
||||
|
||||
|
||||
void SCRIPTING_TOOL::Reset( RESET_REASON aReason )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool SCRIPTING_TOOL::Init()
|
||||
{
|
||||
PyLOCK lock;
|
||||
PyObject* mod_name = PyUnicode_FromString( "_pcbnew" );
|
||||
|
||||
if( PyObject* existing_mod = PyImport_GetModule( mod_name ) )
|
||||
{
|
||||
Py_DecRef( existing_mod );
|
||||
}
|
||||
else
|
||||
{
|
||||
KIFACE* kiface = frame()->Kiway().KiFACE( KIWAY::FACE_PCB );
|
||||
initfunc pcbnew_init = reinterpret_cast<initfunc>( kiface->IfaceOrAddress( KIFACE_SCRIPTING_LEGACY ) );
|
||||
PyImport_AddModule( "_pcbnew" );
|
||||
PyObject* mod = pcbnew_init();
|
||||
PyObject* sys_mod = PyImport_GetModuleDict();
|
||||
PyDict_SetItemString( sys_mod, "_pcbnew", mod );
|
||||
Py_DECREF( mod );
|
||||
}
|
||||
|
||||
Py_DecRef( mod_name );
|
||||
|
||||
// Load pcbnew inside Python and load all the user plugins and package-based plugins
|
||||
{
|
||||
using namespace pybind11::literals;
|
||||
|
||||
auto locals = pybind11::dict( "sys_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( false ) ),
|
||||
"user_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( true ) ) );
|
||||
|
||||
pybind11::exec( R"(
|
||||
import sys
|
||||
import pcbnew
|
||||
pcbnew.LoadPlugins( sys_path, user_path )
|
||||
)", pybind11::globals(), locals );
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int SCRIPTING_TOOL::reloadPlugins( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
if( !m_isFootprintEditor )
|
||||
// Reload Python plugins if they are newer than the already loaded, and load new plugins
|
||||
// Remove all action plugins so that we don't keep references to old versions
|
||||
ACTION_PLUGINS::UnloadAll();
|
||||
|
||||
{
|
||||
PyLOCK lock;
|
||||
|
||||
using namespace pybind11::literals;
|
||||
auto locals = pybind11::dict( "sys_path"_a = SCRIPTING::PyScriptingPath( false ),
|
||||
"user_path"_a = SCRIPTING::PyScriptingPath( true ) );
|
||||
|
||||
pybind11::exec( R"(
|
||||
import sys
|
||||
import pcbnew
|
||||
pcbnew.LoadPlugins( sys_path, user_path )
|
||||
)", pybind11::globals(), locals );
|
||||
}
|
||||
|
||||
if( !m_isFootprintEditor )
|
||||
{
|
||||
// Action plugins can be modified, therefore the plugins menu must be updated:
|
||||
frame()->ReCreateMenuBar();
|
||||
// Recreate top toolbar to add action plugin buttons
|
||||
frame()->ReCreateHToolbar();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int SCRIPTING_TOOL::showPluginFolder( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
#ifdef __WXMAC__
|
||||
wxString msg;
|
||||
|
||||
// Quote in case there are spaces in the path.
|
||||
msg.Printf( "open \"%s\"", SCRIPTING::PyPluginsPath( true ) );
|
||||
|
||||
system( msg.c_str() );
|
||||
#else
|
||||
wxString pypath( SCRIPTING::PyPluginsPath( true ) );
|
||||
|
||||
// Quote in case there are spaces in the path.
|
||||
AddDelimiterString( pypath );
|
||||
|
||||
wxLaunchDefaultApplication( pypath );
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void SCRIPTING_TOOL::setTransitions()
|
||||
{
|
||||
|
||||
Go( &SCRIPTING_TOOL::reloadPlugins, PCB_ACTIONS::pluginsReload.MakeEvent() );
|
||||
Go( &SCRIPTING_TOOL::showPluginFolder, PCB_ACTIONS::pluginsShowFolder.MakeEvent() );
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2021 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 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, you may find one here:
|
||||
* http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 3 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef PCBNEW_PCB_SCRIPTING_TOOL_H_
|
||||
#define PCBNEW_PCB_SCRIPTING_TOOL_H_
|
||||
|
||||
|
||||
#include <tools/pcb_tool_base.h>
|
||||
|
||||
class ACTION_MENU;
|
||||
|
||||
/**
|
||||
* Tool relating to pads and pad settings.
|
||||
*/
|
||||
class SCRIPTING_TOOL : public PCB_TOOL_BASE
|
||||
{
|
||||
public:
|
||||
SCRIPTING_TOOL();
|
||||
~SCRIPTING_TOOL();
|
||||
|
||||
///< React to model/view changes
|
||||
void Reset( RESET_REASON aReason ) override;
|
||||
|
||||
///< Basic initialization
|
||||
bool Init() override;
|
||||
|
||||
private:
|
||||
|
||||
///< Reload Python plugins and reset toolbar (if in pcbnew)
|
||||
int reloadPlugins( const TOOL_EVENT& aEvent );
|
||||
|
||||
///< Open the user's plugin folder in the system browser
|
||||
int showPluginFolder( const TOOL_EVENT& aEvent );
|
||||
|
||||
///< Bind handlers to corresponding TOOL_ACTIONs.
|
||||
void setTransitions() override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif /* PCBNEW_PCB_SCRIPTING_TOOL_H_ */
|
|
@ -197,6 +197,7 @@ void PCB_EDIT_FRAME::OnActionPluginMenu( wxCommandEvent& aEvent )
|
|||
RunActionPlugin( actionPlugin );
|
||||
}
|
||||
|
||||
|
||||
void PCB_EDIT_FRAME::OnActionPluginButton( wxCommandEvent& aEvent )
|
||||
{
|
||||
ACTION_PLUGIN* actionPlugin = ACTION_PLUGINS::GetActionByButton( aEvent.GetId() );
|
||||
|
|
|
@ -49,35 +49,6 @@
|
|||
|
||||
#include <config.h>
|
||||
|
||||
/**
|
||||
* Initialize the python environment and publish the Pcbnew interface inside it.
|
||||
*
|
||||
* This initializes all the wxPython interface and returns the python thread control structure
|
||||
*/
|
||||
bool pcbnewInitPythonScripting( const char* aStockScriptingPath, const char* aUserScriptingPath )
|
||||
{
|
||||
int retv;
|
||||
char cmd[1024];
|
||||
|
||||
// Load pcbnew inside Python and load all the user plugins and package-based plugins
|
||||
{
|
||||
PyLOCK lock;
|
||||
|
||||
// Load os so that we can modify the environment variables through python
|
||||
snprintf( cmd, sizeof( cmd ), "import sys, os, traceback\n"
|
||||
"sys.path.append(\".\")\n"
|
||||
"import pcbnew\n"
|
||||
"pcbnew.LoadPlugins(\"%s\", \"%s\")",
|
||||
aStockScriptingPath, aUserScriptingPath );
|
||||
retv = PyRun_SimpleString( cmd );
|
||||
|
||||
if( retv != 0 )
|
||||
wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, cmd );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run a python method from the pcbnew module.
|
||||
|
|
|
@ -27,11 +27,6 @@
|
|||
#include <wx/string.h>
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the Python engine inside pcbnew.
|
||||
*/
|
||||
bool pcbnewInitPythonScripting( const char* aStockScriptingPath, const char* aUserScriptingPath );
|
||||
|
||||
/**
|
||||
* Collect the list of python scripts which could not be loaded.
|
||||
*
|
||||
|
|
|
@ -539,6 +539,22 @@ TOOL_ACTION PCB_ACTIONS::defaultPadProperties( "pcbnew.PadTool.defaultPadPropert
|
|||
BITMAPS::options_pad );
|
||||
|
||||
|
||||
// SCRIPTING TOOL
|
||||
//
|
||||
TOOL_ACTION PCB_ACTIONS::pluginsReload( "pcbnew.ScriptingTool.pluginsReload",
|
||||
AS_GLOBAL, 0, "",
|
||||
_( "Refresh Plugins" ), _( "Reload all python plugins and refresh plugin menus" ),
|
||||
BITMAPS::reload );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::pluginsShowFolder( "pcbnew.ScriptingTool.pluginsShowFolder",
|
||||
AS_GLOBAL, 0, "",
|
||||
#ifdef __WXMAC__
|
||||
_( "Reveal Plugin Folder in Finder" ), _( "Reveals the plugins folder in a Finder window" ),
|
||||
#else
|
||||
_( "Open Plugin Directory" ), _( "Opens the directory in the default system file manager" ),
|
||||
#endif
|
||||
BITMAPS::directory_open );
|
||||
|
||||
// BOARD_EDITOR_CONTROL
|
||||
//
|
||||
TOOL_ACTION PCB_ACTIONS::boardSetup( "pcbnew.EditorControl.boardSetup",
|
||||
|
|
|
@ -315,6 +315,10 @@ public:
|
|||
/// Duplicate zone onto another layer
|
||||
static TOOL_ACTION zoneDuplicate;
|
||||
|
||||
/// Scripting Actions
|
||||
static TOOL_ACTION pluginsReload;
|
||||
static TOOL_ACTION pluginsShowFolder;
|
||||
|
||||
// Global edit tool
|
||||
static TOOL_ACTION boardSetup;
|
||||
static TOOL_ACTION editTracksAndVias;
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include <macros.h>
|
||||
|
||||
#include <kiface_ids.h>
|
||||
#include <kiway.h>
|
||||
#include <paths.h>
|
||||
#include <pgm_base.h>
|
||||
#include <settings/settings_manager.h>
|
||||
|
@ -52,22 +51,15 @@
|
|||
|
||||
#include <config.h>
|
||||
|
||||
using initfunc = PyObject* (*)(void);
|
||||
|
||||
|
||||
SCRIPTING::SCRIPTING( KIWAY* aKiway )
|
||||
SCRIPTING::SCRIPTING()
|
||||
{
|
||||
int retv;
|
||||
char cmd[1024];
|
||||
|
||||
scriptingSetup();
|
||||
|
||||
KIFACE* pcbnew_kiface = nullptr;
|
||||
|
||||
pcbnew_kiface = aKiway->KiFACE( KIWAY::FACE_PCB );
|
||||
initfunc pcbnew_init = reinterpret_cast<initfunc>( pcbnew_kiface->IfaceOrAddress( KIFACE_SCRIPTING_LEGACY ) );
|
||||
PyImport_AppendInittab( "_pcbnew", pcbnew_init );
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Under vcpkg/msvc, we need to explicitly set the python home
|
||||
// or else it'll start consuming system python registry keys and the like instead
|
||||
|
@ -85,35 +77,12 @@ SCRIPTING::SCRIPTING( KIWAY* aKiway )
|
|||
Py_SetPythonHome( pyHome.GetFullPath().c_str() );
|
||||
}
|
||||
#endif
|
||||
//
|
||||
// Py_Initialize();
|
||||
|
||||
pybind11::initialize_interpreter();
|
||||
|
||||
// PySys_SetArgv( Pgm().App().argc, Pgm().App().argv );
|
||||
|
||||
#if PY_VERSION_HEX < 0x03070000 // PyEval_InitThreads() is called by Py_Initialize() starting with version 3.7
|
||||
PyEval_InitThreads();
|
||||
#endif // if PY_VERSION_HEX < 0x03070000
|
||||
|
||||
// Save the current Python thread state and release the
|
||||
// Global Interpreter Lock.
|
||||
m_python_thread_state = PyEval_SaveThread();
|
||||
|
||||
// Load pcbnew inside Python and load all the user plugins and package-based plugins
|
||||
{
|
||||
PyLOCK lock;
|
||||
|
||||
// Load os so that we can modify the environment variables through python
|
||||
snprintf( cmd, sizeof( cmd ), "import sys, os, traceback\n"
|
||||
"sys.path.append(\".\")\n"
|
||||
"import pcbnew\n"
|
||||
"pcbnew.LoadPlugins(\"%s\", \"%s\")",
|
||||
TO_UTF8( PyScriptingPath() ), TO_UTF8( PyScriptingPath( true) ) );
|
||||
retv = PyRun_SimpleString( cmd );
|
||||
|
||||
if( retv != 0 )
|
||||
wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, cmd );
|
||||
}
|
||||
}
|
||||
|
||||
SCRIPTING::~SCRIPTING()
|
||||
|
@ -316,6 +285,7 @@ void UpdatePythonEnvVar( const wxString& aVar, const wxString& aValue )
|
|||
|
||||
snprintf( cmd, sizeof( cmd ),
|
||||
"# coding=utf-8\n" // The values could potentially be UTF8
|
||||
"import os\n"
|
||||
"os.environ[\"%s\"]=\"%s\"\n",
|
||||
TO_UTF8( escapedVar ),
|
||||
TO_UTF8( escapedVal ) );
|
||||
|
@ -444,7 +414,7 @@ wxString PyErrStringWithTraceback()
|
|||
/**
|
||||
* Find the Python scripting path.
|
||||
*/
|
||||
wxString PyScriptingPath( bool aUserPath )
|
||||
wxString SCRIPTING::PyScriptingPath( bool aUserPath )
|
||||
{
|
||||
wxString path;
|
||||
|
||||
|
@ -471,7 +441,7 @@ wxString PyScriptingPath( bool aUserPath )
|
|||
}
|
||||
|
||||
|
||||
wxString PyPluginsPath( bool aUserPath )
|
||||
wxString SCRIPTING::PyPluginsPath( bool aUserPath )
|
||||
{
|
||||
// Note we are using unix path separator, because window separator sometimes
|
||||
// creates issues when passing a command string to a python method by PyRun_SimpleString
|
||||
|
|
|
@ -45,12 +45,10 @@
|
|||
#include <wx/string.h>
|
||||
#include <wx/arrstr.h>
|
||||
|
||||
class KIWAY;
|
||||
|
||||
class SCRIPTING
|
||||
{
|
||||
public:
|
||||
SCRIPTING( KIWAY* aKiway );
|
||||
SCRIPTING();
|
||||
~SCRIPTING();
|
||||
|
||||
/// We do not allow secondary creation of the scripting system
|
||||
|
@ -59,13 +57,14 @@ public:
|
|||
|
||||
static bool IsWxAvailable();
|
||||
|
||||
static wxString PyScriptingPath( bool aUserPath = false );
|
||||
static wxString PyPluginsPath( bool aUserPath = false );
|
||||
|
||||
private:
|
||||
|
||||
bool scriptingSetup();
|
||||
|
||||
PyThreadState* m_python_thread_state;
|
||||
|
||||
KIWAY* aKiway;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -93,7 +92,4 @@ wxString PyStringToWx( PyObject* str );
|
|||
wxArrayString PyArrayStringToWx( PyObject* arr );
|
||||
wxString PyErrStringWithTraceback();
|
||||
|
||||
wxString PyScriptingPath( bool aUserPath = false );
|
||||
wxString PyPluginsPath( bool aUserPath = false );
|
||||
|
||||
#endif // __PYTHON_SCRIPTING_H
|
||||
|
|
Loading…
Reference in New Issue