Refactor; add user control over API server

This commit is contained in:
Jon Evans 2024-01-17 22:21:28 -05:00
parent a3b6ab48a4
commit 6bd02cae6d
19 changed files with 857 additions and 515 deletions

View File

@ -182,8 +182,11 @@ set( KICOMMON_SRCS
if( KICAD_IPC_API ) if( KICAD_IPC_API )
set( KICOMMON_SRCS set( KICOMMON_SRCS
${KICOMMON_SRCS} ${KICOMMON_SRCS}
api/api_handler.cpp
api/api_handler_common.cpp
api/api_plugin.cpp api/api_plugin.cpp
api/api_plugin_manager.cpp api/api_plugin_manager.cpp
api/api_server.cpp
../scripting/python_manager.cpp ../scripting/python_manager.cpp
) )
@ -226,6 +229,12 @@ if( KICAD_USE_SENTRY )
set_property(SOURCE pgm_base.cpp APPEND PROPERTY COMPILE_DEFINITIONS KICAD_SENTRY_DSN="${KICAD_SENTRY_DSN}") set_property(SOURCE pgm_base.cpp APPEND PROPERTY COMPILE_DEFINITIONS KICAD_SENTRY_DSN="${KICAD_SENTRY_DSN}")
endif() endif()
if( KICAD_IPC_API )
target_link_libraries( kicommon
kinng
)
endif()
include( ${KICAD_CMAKE_MODULE_PATH}/KiCadVersion.cmake ) include( ${KICAD_CMAKE_MODULE_PATH}/KiCadVersion.cmake )
include( ${KICAD_CMAKE_MODULE_PATH}/CreateGitVersionHeader.cmake ) include( ${KICAD_CMAKE_MODULE_PATH}/CreateGitVersionHeader.cmake )
create_git_version_header(${CMAKE_SOURCE_DIR}) create_git_version_header(${CMAKE_SOURCE_DIR})
@ -267,6 +276,7 @@ target_include_directories( kicommon
${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}
$<TARGET_PROPERTY:magic_enum,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:magic_enum,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:pegtl,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:pegtl,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:expected,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:kiapi,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:kiapi,INTERFACE_INCLUDE_DIRECTORIES>
) )
@ -349,8 +359,8 @@ set( COMMON_DLG_SRCS
dialogs/panel_mouse_settings_base.cpp dialogs/panel_mouse_settings_base.cpp
dialogs/panel_packages_and_updates.cpp dialogs/panel_packages_and_updates.cpp
dialogs/panel_packages_and_updates_base.cpp dialogs/panel_packages_and_updates_base.cpp
dialogs/panel_python_settings.cpp dialogs/panel_plugin_settings.cpp
dialogs/panel_python_settings_base.cpp dialogs/panel_plugin_settings_base.cpp
dialogs/panel_setup_netclasses.cpp dialogs/panel_setup_netclasses.cpp
dialogs/panel_setup_netclasses_base.cpp dialogs/panel_setup_netclasses_base.cpp
dialogs/panel_setup_severities.cpp dialogs/panel_setup_severities.cpp
@ -691,7 +701,6 @@ add_dependencies( common pegtl )
target_include_directories( common PUBLIC target_include_directories( common PUBLIC
$<TARGET_PROPERTY:pegtl,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:pegtl,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:magic_enum,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:magic_enum,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:expected,INTERFACE_INCLUDE_DIRECTORIES>
) )
target_include_directories( common SYSTEM PUBLIC target_include_directories( common SYSTEM PUBLIC

View File

@ -309,7 +309,7 @@ void API_PLUGIN_MANAGER::processNextJob( wxCommandEvent& aEvent )
{ {
wxLogTrace( traceApi, wxString::Format( "Manager: creating Python env at %s", wxLogTrace( traceApi, wxString::Format( "Manager: creating Python env at %s",
job.env_path ) ); job.env_path ) );
PYTHON_MANAGER manager( Pgm().GetCommonSettings()->m_Python.interpreter_path ); PYTHON_MANAGER manager( Pgm().GetCommonSettings()->m_Api.python_interpreter );
manager.Execute( wxString::Format( wxS( "-m venv %s"), job.env_path ), manager.Execute( wxString::Format( wxS( "-m venv %s"), job.env_path ),
[=]( int aRetVal, const wxString& aOutput, const wxString& aError ) [=]( int aRetVal, const wxString& aOutput, const wxString& aError )

View File

@ -21,14 +21,17 @@
#include <wx/app.h> #include <wx/app.h>
#include <wx/datetime.h> #include <wx/datetime.h>
#include <wx/event.h> #include <wx/event.h>
#include <wx/stdpaths.h>
#include <advanced_config.h> #include <advanced_config.h>
#include <api/api_plugin_manager.h> // traceApi
#include <api/api_server.h> #include <api/api_server.h>
#include <api/api_handler_common.h> #include <api/api_handler_common.h>
#include <kiid.h> #include <kiid.h>
#include <kinng.h> #include <kinng.h>
#include <paths.h> #include <paths.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <settings/common_settings.h>
#include <string_utils.h> #include <string_utils.h>
#include <api/common/envelope.pb.h> #include <api/common/envelope.pb.h>
@ -47,9 +50,43 @@ KICAD_API_SERVER::KICAD_API_SERVER() :
m_token( KIID().AsStdString() ), m_token( KIID().AsStdString() ),
m_readyToReply( false ) m_readyToReply( false )
{ {
m_server = std::make_unique<KINNG_REQUEST_SERVER>(); if( !Pgm().GetCommonSettings()->m_Api.enable_server )
{
wxLogTrace( traceApi, "Server: disabled by user preferences." );
return;
}
wxFileName socket;
#ifdef __WXMAC__
socket.AssignDir( wxS( "/tmp" ) );
#else
socket.AssignDir( wxStandardPaths::Get().GetTempDir() );
#endif
socket.AppendDir( wxS( "kicad" ) );
socket.SetFullName( wxS( "api.sock" ) );
if( !PATHS::EnsurePathExists( socket.GetPath() ) )
{
wxLogTrace( traceApi, wxString::Format( "Server: socket path %s could not be created",
socket.GetPath() ) );
return;
}
if( socket.FileExists() )
{
socket.SetFullName( wxString::Format( wxS( "api-%ul.sock" ), ::wxGetProcessId() ) );
if( socket.FileExists() )
{
wxLogTrace( traceApi, wxString::Format( "Server: PID socket path %s already exists!",
socket.GetFullPath() ) );
return;
}
}
m_server = std::make_unique<KINNG_REQUEST_SERVER>(
fmt::format( "ipc://{}", socket.GetFullPath().ToStdString() ) );
m_server->SetCallback( [&]( std::string* aRequest ) { onApiRequest( aRequest ); } ); m_server->SetCallback( [&]( std::string* aRequest ) { onApiRequest( aRequest ); } );
m_socketPath = m_server->SocketPath();
m_commonHandler = std::make_unique<API_HANDLER_COMMON>(); m_commonHandler = std::make_unique<API_HANDLER_COMMON>();
RegisterHandler( m_commonHandler.get() ); RegisterHandler( m_commonHandler.get() );
@ -60,7 +97,8 @@ KICAD_API_SERVER::KICAD_API_SERVER() :
if( ADVANCED_CFG::GetCfg().m_EnableAPILogging ) if( ADVANCED_CFG::GetCfg().m_EnableAPILogging )
PATHS::EnsurePathExists( PATHS::GetLogsPath() ); PATHS::EnsurePathExists( PATHS::GetLogsPath() );
log( "--- KiCad API server started ---\n" ); log( fmt::format( "--- KiCad API server started at {} ---\n", SocketPath() ) );
wxLogTrace( traceApi, wxString::Format( "Server: listening at %s", SocketPath() ) );
Bind( API_REQUEST_EVENT, &KICAD_API_SERVER::handleApiEvent, this ); Bind( API_REQUEST_EVENT, &KICAD_API_SERVER::handleApiEvent, this );
} }
@ -71,6 +109,12 @@ KICAD_API_SERVER::~KICAD_API_SERVER()
} }
bool KICAD_API_SERVER::Running() const
{
return m_server && m_server->Running();
}
void KICAD_API_SERVER::RegisterHandler( API_HANDLER* aHandler ) void KICAD_API_SERVER::RegisterHandler( API_HANDLER* aHandler )
{ {
wxCHECK( aHandler, /* void */ ); wxCHECK( aHandler, /* void */ );
@ -84,6 +128,12 @@ void KICAD_API_SERVER::DeregisterHandler( API_HANDLER* aHandler )
} }
std::string KICAD_API_SERVER::SocketPath() const
{
return m_server ? m_server->SocketPath() : "";
}
void KICAD_API_SERVER::onApiRequest( std::string* aRequest ) void KICAD_API_SERVER::onApiRequest( std::string* aRequest )
{ {
if( !m_readyToReply ) if( !m_readyToReply )

View File

@ -18,7 +18,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <dialogs/panel_python_settings.h> #include <dialogs/panel_plugin_settings.h>
#include <api/api_server.h>
#include <widgets/ui_common.h> #include <widgets/ui_common.h>
#include <pgm_base.h> #include <pgm_base.h>
#include <python_manager.h> #include <python_manager.h>
@ -26,70 +27,98 @@
#include <settings/settings_manager.h> #include <settings/settings_manager.h>
PANEL_PYTHON_SETTINGS::PANEL_PYTHON_SETTINGS( wxWindow* aParent ) : PANEL_PLUGIN_SETTINGS::PANEL_PLUGIN_SETTINGS( wxWindow* aParent ) :
PANEL_PYTHON_SETTINGS_BASE( aParent ) PANEL_PLUGIN_SETTINGS_BASE( aParent )
{ {
wxFont helpFont = KIUI::GetInfoFont( this ).Italic(); wxFont helpFont = KIUI::GetInfoFont( this ).Italic();
m_stPythonStatus->SetFont( helpFont ); m_stPythonStatus->SetFont( helpFont );
m_stApiStatus->SetFont( helpFont );
} }
void PANEL_PYTHON_SETTINGS::ResetPanel() void PANEL_PLUGIN_SETTINGS::ResetPanel()
{ {
} }
bool PANEL_PYTHON_SETTINGS::TransferDataToWindow() bool PANEL_PLUGIN_SETTINGS::TransferDataToWindow()
{ {
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager(); SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
COMMON_SETTINGS* settings = mgr.GetCommonSettings();
m_pickerPythonInterpreter->SetFileName( mgr.GetCommonSettings()->m_Python.interpreter_path ); m_cbEnableApi->SetValue( settings->m_Api.enable_server );
validateInterpreter(); m_pickerPythonInterpreter->SetFileName( settings->m_Api.python_interpreter );
validatePythonInterpreter();
updateApiStatusText();
return true; return true;
} }
bool PANEL_PYTHON_SETTINGS::TransferDataFromWindow() bool PANEL_PLUGIN_SETTINGS::TransferDataFromWindow()
{ {
SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager(); SETTINGS_MANAGER& mgr = Pgm().GetSettingsManager();
COMMON_SETTINGS* settings = mgr.GetCommonSettings();
wxString interpreter = m_pickerPythonInterpreter->GetTextCtrlValue(); wxString interpreter = m_pickerPythonInterpreter->GetTextCtrlValue();
if( m_interpreterValid || interpreter.IsEmpty() ) if( m_pythonInterpreterValid || interpreter.IsEmpty() )
mgr.GetCommonSettings()->m_Python.interpreter_path = interpreter; settings->m_Api.python_interpreter = interpreter;
settings->m_Api.enable_server = m_cbEnableApi->GetValue();
return true; return true;
} }
void PANEL_PYTHON_SETTINGS::OnPythonInterpreterChanged( wxFileDirPickerEvent& event ) void PANEL_PLUGIN_SETTINGS::OnPythonInterpreterChanged( wxFileDirPickerEvent& event )
{ {
validateInterpreter(); validatePythonInterpreter();
} }
void PANEL_PYTHON_SETTINGS::OnBtnDetectAutomaticallyClicked( wxCommandEvent& aEvent ) void PANEL_PLUGIN_SETTINGS::OnBtnDetectAutomaticallyClicked( wxCommandEvent& aEvent )
{ {
#ifdef __WXMSW__ wxString interpreter = PYTHON_MANAGER::FindPythonInterpreter();
// TODO(JE) where
#else
wxArrayString output;
if( 0 == wxExecute( wxS( "which -a python" ), output, wxEXEC_SYNC ) ) if( !interpreter.IsEmpty() )
{ {
if( !output.IsEmpty() ) m_pickerPythonInterpreter->SetPath( interpreter );
{ validatePythonInterpreter();
m_pickerPythonInterpreter->SetPath( output[0] );
validateInterpreter();
}
} }
#endif
} }
void PANEL_PYTHON_SETTINGS::validateInterpreter() void PANEL_PLUGIN_SETTINGS::OnEnableApiChecked( wxCommandEvent& aEvent )
{ {
m_interpreterValid = false; validatePythonInterpreter();
updateApiStatusText();
}
void PANEL_PLUGIN_SETTINGS::updateApiStatusText()
{
if( m_cbEnableApi->GetValue() && Pgm().GetApiServer().Running() )
{
m_stApiStatus->SetLabel( wxString::Format( _( "Listening at %s" ),
Pgm().GetApiServer().SocketPath() ) );
}
else
{
m_stApiStatus->SetLabel( wxEmptyString );
}
}
void PANEL_PLUGIN_SETTINGS::validatePythonInterpreter()
{
if( !m_cbEnableApi->GetValue() )
{
m_stPythonStatus->SetLabel( _( "KiCad API is not enabled; external Python plugins will "
"not be available" ) );
return;
}
m_pythonInterpreterValid = false;
wxFileName pythonExe( m_pickerPythonInterpreter->GetTextCtrlValue() ); wxFileName pythonExe( m_pickerPythonInterpreter->GetTextCtrlValue() );
@ -110,7 +139,7 @@ void PANEL_PYTHON_SETTINGS::validateInterpreter()
if( aRetCode == 0 && aStdOut.Contains( wxS( "Python 3" ) ) ) if( aRetCode == 0 && aStdOut.Contains( wxS( "Python 3" ) ) )
{ {
msg = wxString::Format( _( "Found %s" ), aStdOut ); msg = wxString::Format( _( "Found %s" ), aStdOut );
m_interpreterValid = true; m_pythonInterpreterValid = true;
} }
else else
{ {

View File

@ -0,0 +1,91 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf-dirty)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "panel_plugin_settings_base.h"
///////////////////////////////////////////////////////////////////////////
PANEL_PLUGIN_SETTINGS_BASE::PANEL_PLUGIN_SETTINGS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : RESETTABLE_PANEL( parent, id, pos, size, style, name )
{
wxBoxSizer* bPanelSizer;
bPanelSizer = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* bSizer8;
bSizer8 = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizerServer;
sbSizerServer = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("KiCad API") ), wxVERTICAL );
m_staticText3 = new wxStaticText( sbSizerServer->GetStaticBox(), wxID_ANY, _("When the KiCad API is enabled, plugins and other software running on this computer can connect to KiCad."), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText3->Wrap( -1 );
sbSizerServer->Add( m_staticText3, 0, wxALL, 5 );
m_cbEnableApi = new wxCheckBox( sbSizerServer->GetStaticBox(), wxID_ANY, _("Enable KiCad API"), wxDefaultPosition, wxDefaultSize, 0 );
m_cbEnableApi->SetToolTip( _("Enable the KiCad API. Doing so will allow third-party software running on your computer to access KiCad.") );
sbSizerServer->Add( m_cbEnableApi, 0, wxALL, 5 );
m_stApiStatus = new wxStaticText( sbSizerServer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
m_stApiStatus->Wrap( -1 );
sbSizerServer->Add( m_stApiStatus, 0, wxALL, 5 );
bSizer8->Add( sbSizerServer, 0, wxALL|wxEXPAND, 5 );
wxStaticBoxSizer* sbSizerPython;
sbSizerPython = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Python Interpreter") ), wxVERTICAL );
wxBoxSizer* bSizer4;
bSizer4 = new wxBoxSizer( wxHORIZONTAL );
m_staticText2 = new wxStaticText( sbSizerPython->GetStaticBox(), wxID_ANY, _("Path to Python interpreter:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText2->Wrap( -1 );
bSizer4->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_pickerPythonInterpreter = new wxFilePickerCtrl( sbSizerPython->GetStaticBox(), wxID_ANY, wxEmptyString, _("Select the path to a Python interpreter"), _("*.*"), wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE|wxFLP_USE_TEXTCTRL );
bSizer4->Add( m_pickerPythonInterpreter, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_btnDetectAutomatically = new wxButton( sbSizerPython->GetStaticBox(), wxID_ANY, _("Detect Automatically"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer4->Add( m_btnDetectAutomatically, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
sbSizerPython->Add( bSizer4, 0, wxEXPAND, 5 );
m_stPythonStatus = new wxStaticText( sbSizerPython->GetStaticBox(), wxID_ANY, _("No Python interpreter chosen; external Python plugins will not be available"), wxDefaultPosition, wxDefaultSize, 0 );
m_stPythonStatus->Wrap( -1 );
m_stPythonStatus->SetToolTip( _("Python interpreter status") );
sbSizerPython->Add( m_stPythonStatus, 0, wxALL, 5 );
bSizer8->Add( sbSizerPython, 0, wxALL|wxEXPAND, 5 );
bSizer8->Add( 0, 0, 1, wxEXPAND, 5 );
bPanelSizer->Add( bSizer8, 1, wxEXPAND, 5 );
this->SetSizer( bPanelSizer );
this->Layout();
bPanelSizer->Fit( this );
// Connect Events
m_cbEnableApi->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_PLUGIN_SETTINGS_BASE::OnEnableApiChecked ), NULL, this );
m_pickerPythonInterpreter->Connect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( PANEL_PLUGIN_SETTINGS_BASE::OnPythonInterpreterChanged ), NULL, this );
m_btnDetectAutomatically->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PLUGIN_SETTINGS_BASE::OnBtnDetectAutomaticallyClicked ), NULL, this );
}
PANEL_PLUGIN_SETTINGS_BASE::~PANEL_PLUGIN_SETTINGS_BASE()
{
// Disconnect Events
m_cbEnableApi->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PANEL_PLUGIN_SETTINGS_BASE::OnEnableApiChecked ), NULL, this );
m_pickerPythonInterpreter->Disconnect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( PANEL_PLUGIN_SETTINGS_BASE::OnPythonInterpreterChanged ), NULL, this );
m_btnDetectAutomatically->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PLUGIN_SETTINGS_BASE::OnBtnDetectAutomaticallyClicked ), NULL, this );
}

View File

@ -0,0 +1,580 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="17"/>
<object class="Project" expanded="true">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">panel_plugin_settings_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">PanelPluginSettings</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">1</property>
<property name="use_microsoft_bom">0</property>
<object class="Panel" expanded="true">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">PANEL_PLUGIN_SETTINGS_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare</property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bPanelSizer</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bSizer8</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStaticBoxSizer" expanded="true">
<property name="id">wxID_ANY</property>
<property name="label">KiCad API</property>
<property name="minimum_size"></property>
<property name="name">sbSizerServer</property>
<property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<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="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="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">When the KiCad API is enabled, plugins and other software running on this computer can connect to KiCad.</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_staticText3</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="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"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="true">
<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="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Enable KiCad API</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_cbEnableApi</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="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">Enable the KiCad API. Doing so will allow third-party software running on your computer to access KiCad.</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>
<event name="OnCheckBox">OnEnableApiChecked</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<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="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="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label"></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_stApiStatus</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="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"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStaticBoxSizer" expanded="true">
<property name="id">wxID_ANY</property>
<property name="label">Python Interpreter</property>
<property name="minimum_size"></property>
<property name="name">sbSizerPython</property>
<property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bSizer4</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<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="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="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Path to Python interpreter:</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_staticText2</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="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"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">1</property>
<object class="wxFilePickerCtrl" expanded="true">
<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="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="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="message">Select the path to a Python interpreter</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_pickerPythonInterpreter</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="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxFLP_DEFAULT_STYLE|wxFLP_USE_TEXTCTRL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></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="value"></property>
<property name="wildcard">*.*</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnFileChanged">OnPythonInterpreterChanged</event>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxButton" expanded="true">
<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="auth_needed">0</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="drag_accept_files">0</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">Detect Automatically</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_btnDetectAutomatically</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"></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>
<event name="OnButtonClick">OnBtnDetectAutomaticallyClicked</event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="true">
<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="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="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">No Python interpreter chosen; external Python plugins will not be available</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_stPythonStatus</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">public</property>
<property name="pin_button">1</property>
<property name="pos"></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">Python interpreter status</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="true">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3) // C++ code generated with wxFormBuilder (version 4.0.0-0-g0efcecf-dirty)
// http://www.wxformbuilder.org/ // http://www.wxformbuilder.org/
// //
// PLEASE DO *NOT* EDIT THIS FILE! // PLEASE DO *NOT* EDIT THIS FILE!
@ -17,30 +17,35 @@
#include <wx/font.h> #include <wx/font.h>
#include <wx/colour.h> #include <wx/colour.h>
#include <wx/settings.h> #include <wx/settings.h>
#include <wx/checkbox.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/filepicker.h> #include <wx/filepicker.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/bitmap.h> #include <wx/bitmap.h>
#include <wx/image.h> #include <wx/image.h>
#include <wx/icon.h> #include <wx/icon.h>
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/panel.h> #include <wx/panel.h>
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/// Class PANEL_PYTHON_SETTINGS_BASE /// Class PANEL_PLUGIN_SETTINGS_BASE
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class PANEL_PYTHON_SETTINGS_BASE : public RESETTABLE_PANEL class PANEL_PLUGIN_SETTINGS_BASE : public RESETTABLE_PANEL
{ {
private: private:
protected: protected:
wxStaticText* m_staticText3;
wxCheckBox* m_cbEnableApi;
wxStaticText* m_stApiStatus;
wxStaticText* m_staticText2; wxStaticText* m_staticText2;
wxFilePickerCtrl* m_pickerPythonInterpreter; wxFilePickerCtrl* m_pickerPythonInterpreter;
wxButton* m_btnDetectAutomatically; wxButton* m_btnDetectAutomatically;
// Virtual event handlers, override them in your derived class // Virtual event handlers, override them in your derived class
virtual void OnEnableApiChecked( wxCommandEvent& event ) { event.Skip(); }
virtual void OnPythonInterpreterChanged( wxFileDirPickerEvent& event ) { event.Skip(); } virtual void OnPythonInterpreterChanged( wxFileDirPickerEvent& event ) { event.Skip(); }
virtual void OnBtnDetectAutomaticallyClicked( wxCommandEvent& event ) { event.Skip(); } virtual void OnBtnDetectAutomaticallyClicked( wxCommandEvent& event ) { event.Skip(); }
@ -48,9 +53,9 @@ class PANEL_PYTHON_SETTINGS_BASE : public RESETTABLE_PANEL
public: public:
wxStaticText* m_stPythonStatus; wxStaticText* m_stPythonStatus;
PANEL_PYTHON_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString ); PANEL_PLUGIN_SETTINGS_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxEmptyString );
~PANEL_PYTHON_SETTINGS_BASE(); ~PANEL_PLUGIN_SETTINGS_BASE();
}; };

View File

@ -1,70 +0,0 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 3.10.1-0-g8feb16b3)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
///////////////////////////////////////////////////////////////////////////
#include "panel_python_settings_base.h"
///////////////////////////////////////////////////////////////////////////
PANEL_PYTHON_SETTINGS_BASE::PANEL_PYTHON_SETTINGS_BASE( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : RESETTABLE_PANEL( parent, id, pos, size, style, name )
{
wxBoxSizer* bPanelSizer;
bPanelSizer = new wxBoxSizer( wxHORIZONTAL );
wxBoxSizer* bSizer8;
bSizer8 = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizer1;
sbSizer1 = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("Python Interpreter") ), wxVERTICAL );
wxBoxSizer* bSizer4;
bSizer4 = new wxBoxSizer( wxHORIZONTAL );
m_staticText2 = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("Path to Python interpreter:"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText2->Wrap( -1 );
bSizer4->Add( m_staticText2, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_pickerPythonInterpreter = new wxFilePickerCtrl( sbSizer1->GetStaticBox(), wxID_ANY, wxEmptyString, _("Select the path to a Python interpreter"), _("*.*"), wxDefaultPosition, wxDefaultSize, wxFLP_DEFAULT_STYLE|wxFLP_USE_TEXTCTRL );
bSizer4->Add( m_pickerPythonInterpreter, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_btnDetectAutomatically = new wxButton( sbSizer1->GetStaticBox(), wxID_ANY, _("Detect Automatically"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer4->Add( m_btnDetectAutomatically, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
sbSizer1->Add( bSizer4, 0, wxEXPAND, 5 );
m_stPythonStatus = new wxStaticText( sbSizer1->GetStaticBox(), wxID_ANY, _("No Python interpreter chosen; external Python plugins will not be available"), wxDefaultPosition, wxDefaultSize, 0 );
m_stPythonStatus->Wrap( -1 );
m_stPythonStatus->SetToolTip( _("Python interpreter status") );
sbSizer1->Add( m_stPythonStatus, 0, wxALL, 5 );
bSizer8->Add( sbSizer1, 0, wxALL|wxEXPAND, 5 );
bSizer8->Add( 0, 0, 1, wxEXPAND, 5 );
bPanelSizer->Add( bSizer8, 1, wxEXPAND, 5 );
this->SetSizer( bPanelSizer );
this->Layout();
bPanelSizer->Fit( this );
// Connect Events
m_pickerPythonInterpreter->Connect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( PANEL_PYTHON_SETTINGS_BASE::OnPythonInterpreterChanged ), NULL, this );
m_btnDetectAutomatically->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PYTHON_SETTINGS_BASE::OnBtnDetectAutomaticallyClicked ), NULL, this );
}
PANEL_PYTHON_SETTINGS_BASE::~PANEL_PYTHON_SETTINGS_BASE()
{
// Disconnect Events
m_pickerPythonInterpreter->Disconnect( wxEVT_COMMAND_FILEPICKER_CHANGED, wxFileDirPickerEventHandler( PANEL_PYTHON_SETTINGS_BASE::OnPythonInterpreterChanged ), NULL, this );
m_btnDetectAutomatically->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PANEL_PYTHON_SETTINGS_BASE::OnBtnDetectAutomaticallyClicked ), NULL, this );
}

View File

@ -1,371 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="16" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">panel_python_settings_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="image_path_wrapper_function_name"></property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">PanelPythonSettings</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_array_enum">0</property>
<property name="use_enum">1</property>
<property name="use_microsoft_bom">0</property>
<object class="Panel" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">PANEL_PYTHON_SETTINGS_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="subclass">RESETTABLE_PANEL; widgets/resettable_panel.h; Not forward_declare</property>
<property name="tooltip"></property>
<property name="two_step_creation">0</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bPanelSizer</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer8</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxStaticBoxSizer" expanded="1">
<property name="id">wxID_ANY</property>
<property name="label">Python Interpreter</property>
<property name="minimum_size"></property>
<property name="name">sbSizer1</property>
<property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizer4</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" 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="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="default_pane">0</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="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Path to Python interpreter:</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_staticText2</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="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"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="proportion">1</property>
<object class="wxFilePickerCtrl" 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="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="default_pane">0</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="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="message">Select the path to a Python interpreter</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_pickerPythonInterpreter</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="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxFLP_DEFAULT_STYLE|wxFLP_USE_TEXTCTRL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></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="value"></property>
<property name="wildcard">*.*</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnFileChanged">OnPythonInterpreterChanged</event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|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="auth_needed">0</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">Detect Automatically</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_btnDetectAutomatically</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"></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>
<event name="OnButtonClick">OnBtnDetectAutomaticallyClicked</event>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxStaticText" 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="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="default_pane">0</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="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">No Python interpreter chosen; external Python plugins will not be available</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_stPythonStatus</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">public</property>
<property name="pin_button">1</property>
<property name="pos"></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">Python interpreter status</property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</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>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -32,7 +32,7 @@
#include <dialogs/panel_common_settings.h> #include <dialogs/panel_common_settings.h>
#include <dialogs/panel_mouse_settings.h> #include <dialogs/panel_mouse_settings.h>
#include <dialogs/panel_data_collection.h> #include <dialogs/panel_data_collection.h>
#include <dialogs/panel_python_settings.h> #include <dialogs/panel_plugin_settings.h>
#include <eda_dde.h> #include <eda_dde.h>
#include <file_history.h> #include <file_history.h>
#include <id.h> #include <id.h>
@ -1237,7 +1237,7 @@ void EDA_BASE_FRAME::ShowPreferences( wxString aStartPage, wxString aStartParent
} }
#ifdef KICAD_IPC_API #ifdef KICAD_IPC_API
book->AddPage( new PANEL_PYTHON_SETTINGS( book ), _( "Python Scripting" ) ); book->AddPage( new PANEL_PLUGIN_SETTINGS( book ), _( "Plugins" ) );
#endif #endif
// Update all of the action hotkeys. The process of loading the actions through // Update all of the action hotkeys. The process of loading the actions through

View File

@ -77,6 +77,7 @@
#ifdef KICAD_IPC_API #ifdef KICAD_IPC_API
#include <api/api_plugin_manager.h> #include <api/api_plugin_manager.h>
#include <api/api_server.h> #include <api/api_server.h>
#include <python_manager.h>
#endif #endif
/** /**
@ -570,13 +571,20 @@ bool PGM_BASE::InitPgm( bool aHeadless, bool aSkipPyInit, bool aIsUnitTest )
return false; return false;
// Set up built-in environment variables (and override them from the system environment if set) // Set up built-in environment variables (and override them from the system environment if set)
GetCommonSettings()->InitializeEnvironment(); COMMON_SETTINGS* commonSettings = GetCommonSettings();
commonSettings->InitializeEnvironment();
// Load color settings after env is initialized // Load color settings after env is initialized
m_settings_manager->ReloadColorSettings(); m_settings_manager->ReloadColorSettings();
// Load common settings from disk after setting up env vars // Load common settings from disk after setting up env vars
GetSettingsManager().Load( GetCommonSettings() ); GetSettingsManager().Load( commonSettings );
#ifdef KICAD_IPC_API
// If user doesn't have a saved Python interpreter, try (potentially again) to find one
if( commonSettings->m_Api.python_interpreter.IsEmpty() )
commonSettings->m_Api.python_interpreter = PYTHON_MANAGER::FindPythonInterpreter();
#endif
// Init user language *before* calling loadSettings, because // Init user language *before* calling loadSettings, because
// env vars could be incorrectly initialized on Linux // env vars could be incorrectly initialized on Linux
@ -1058,4 +1066,4 @@ PGM_BASE* PgmOrNull()
void SetPgm(PGM_BASE* pgm) void SetPgm(PGM_BASE* pgm)
{ {
process = pgm; process = pgm;
} }

View File

@ -54,7 +54,7 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
m_DoNotShowAgain(), m_DoNotShowAgain(),
m_NetclassPanel(), m_NetclassPanel(),
m_PackageManager(), m_PackageManager(),
m_Python() m_Api()
{ {
/* /*
* Automatic dark mode detection works fine on Mac. * Automatic dark mode detection works fine on Mac.
@ -398,8 +398,11 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
m_params.emplace_back( new PARAM<bool>( "git.useDefaultAuthor", m_params.emplace_back( new PARAM<bool>( "git.useDefaultAuthor",
&m_Git.useDefaultAuthor, true ) ); &m_Git.useDefaultAuthor, true ) );
m_params.emplace_back( new PARAM<wxString>( "python.interpreter_path", m_params.emplace_back( new PARAM<wxString>( "api.interpreter_path",
&m_Python.interpreter_path, wxS( "" ) ) ); &m_Api.python_interpreter, wxS( "" ) ) );
m_params.emplace_back( new PARAM<bool>( "api.enable_server",
&m_Api.enable_server, false ) );
registerMigration( 0, 1, std::bind( &COMMON_SETTINGS::migrateSchema0to1, this ) ); registerMigration( 0, 1, std::bind( &COMMON_SETTINGS::migrateSchema0to1, this ) );
registerMigration( 1, 2, std::bind( &COMMON_SETTINGS::migrateSchema1to2, this ) ); registerMigration( 1, 2, std::bind( &COMMON_SETTINGS::migrateSchema1to2, this ) );

View File

@ -44,6 +44,8 @@ public:
~KICAD_API_SERVER(); ~KICAD_API_SERVER();
bool Running() const;
/** /**
* Adds a new request handler to the server. Each handler maintains its own list of API * Adds a new request handler to the server. Each handler maintains its own list of API
* messages that it knows how to handle, and the server will pass every incoming message to all * messages that it knows how to handle, and the server will pass every incoming message to all
@ -60,7 +62,7 @@ public:
void SetReadyToReply( bool aReady = true ) { m_readyToReply = aReady; } void SetReadyToReply( bool aReady = true ) { m_readyToReply = aReady; }
const std::string& SocketPath() const { return m_socketPath; } std::string SocketPath() const;
const std::string& Token() const { return m_token; } const std::string& Token() const { return m_token; }
@ -87,8 +89,6 @@ private:
std::set<API_HANDLER*> m_handlers; std::set<API_HANDLER*> m_handlers;
std::string m_socketPath;
std::string m_token; std::string m_token;
bool m_readyToReply; bool m_readyToReply;

View File

@ -18,18 +18,18 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KICAD_PANEL_PYTHON_SETTINGS_H #ifndef KICAD_PANEL_PLUGIN_SETTINGS_H
#define KICAD_PANEL_PYTHON_SETTINGS_H #define KICAD_PANEL_PLUGIN_SETTINGS_H
#include <dialogs/panel_python_settings_base.h> #include <dialogs/panel_plugin_settings_base.h>
class PAGED_DIALOG; class PAGED_DIALOG;
class PANEL_PYTHON_SETTINGS : public PANEL_PYTHON_SETTINGS_BASE class PANEL_PLUGIN_SETTINGS : public PANEL_PLUGIN_SETTINGS_BASE
{ {
public: public:
PANEL_PYTHON_SETTINGS( wxWindow* aParent ); PANEL_PLUGIN_SETTINGS( wxWindow* aParent );
void ResetPanel() override; void ResetPanel() override;
@ -39,11 +39,13 @@ protected:
void OnPythonInterpreterChanged( wxFileDirPickerEvent& event ) override; void OnPythonInterpreterChanged( wxFileDirPickerEvent& event ) override;
void OnBtnDetectAutomaticallyClicked( wxCommandEvent& aEvent ) override; void OnBtnDetectAutomaticallyClicked( wxCommandEvent& aEvent ) override;
void OnEnableApiChecked( wxCommandEvent& aEvent ) override;
private: private:
void validateInterpreter(); void updateApiStatusText();
void validatePythonInterpreter();
bool m_interpreterValid; bool m_pythonInterpreterValid;
}; };
#endif //KICAD_PANEL_PYTHON_SETTINGS_H #endif //KICAD_PANEL_PLUGIN_SETTINGS_H

View File

@ -166,9 +166,10 @@ public:
wxString authorEmail; wxString authorEmail;
}; };
struct PYTHON struct API
{ {
wxString interpreter_path; wxString python_interpreter;
bool enable_server;
}; };
COMMON_SETTINGS(); COMMON_SETTINGS();
@ -223,7 +224,7 @@ public:
GIT m_Git; GIT m_Git;
PYTHON m_Python; API m_Api;
}; };
#endif #endif

View File

@ -31,7 +31,7 @@
class KINNG_REQUEST_SERVER class KINNG_REQUEST_SERVER
{ {
public: public:
KINNG_REQUEST_SERVER(); KINNG_REQUEST_SERVER( const std::string& aSocketUrl );
~KINNG_REQUEST_SERVER(); ~KINNG_REQUEST_SERVER();
@ -39,6 +39,8 @@ public:
void Stop(); void Stop();
bool Running() const;
void SetCallback( std::function<void(std::string*)> aFunc ) { m_callback = aFunc; } void SetCallback( std::function<void(std::string*)> aFunc ) { m_callback = aFunc; }
void Reply( const std::string& aReply ); void Reply( const std::string& aReply );

View File

@ -21,18 +21,12 @@
#include <kinng.h> #include <kinng.h>
#include <nng/nng.h> #include <nng/nng.h>
#include <nng/protocol/reqrep0/rep.h> #include <nng/protocol/reqrep0/rep.h>
#include <nng/protocol/reqrep0/req.h>
KINNG_REQUEST_SERVER::KINNG_REQUEST_SERVER() : KINNG_REQUEST_SERVER::KINNG_REQUEST_SERVER( const std::string& aSocketUrl ) :
m_socketUrl( aSocketUrl ),
m_callback() m_callback()
{ {
#ifdef WIN32
m_socketUrl = "ipc://\\.\\pipe\\kicad";
#else
m_socketUrl = "ipc:///tmp/kicad.sock";
#endif
Start(); Start();
} }
@ -43,6 +37,12 @@ KINNG_REQUEST_SERVER::~KINNG_REQUEST_SERVER()
} }
bool KINNG_REQUEST_SERVER::Running() const
{
return m_thread.joinable();
}
bool KINNG_REQUEST_SERVER::Start() bool KINNG_REQUEST_SERVER::Start()
{ {
m_shutdown.store( false ); m_shutdown.store( false );

View File

@ -284,7 +284,7 @@ void PCB_EDIT_FRAME::ReCreateHToolbar()
// Add SWIG and API plugins // Add SWIG and API plugins
bool scriptingAvailable = SCRIPTING::IsWxAvailable(); bool scriptingAvailable = SCRIPTING::IsWxAvailable();
bool haveApiPlugins = bool haveApiPlugins = Pgm().GetCommonSettings()->m_Api.enable_server &&
!Pgm().GetPluginManager().GetActionsForScope( PLUGIN_ACTION_SCOPE::PCB ).empty(); !Pgm().GetPluginManager().GetActionsForScope( PLUGIN_ACTION_SCOPE::PCB ).empty();
if( scriptingAvailable || haveApiPlugins ) if( scriptingAvailable || haveApiPlugins )

View File

@ -18,6 +18,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <wx/filename.h>
#include <wx/stdpaths.h>
#include <qa_utils/wx_utils/unit_test_utils.h> #include <qa_utils/wx_utils/unit_test_utils.h>
#include <kinng.h> #include <kinng.h>
@ -28,7 +31,7 @@ BOOST_AUTO_TEST_SUITE( KiNNG )
BOOST_AUTO_TEST_CASE( CreateIPCResponder ) BOOST_AUTO_TEST_CASE( CreateIPCResponder )
{ {
KINNG_REQUEST_SERVER server; KINNG_REQUEST_SERVER server( wxFileName::CreateTempFileName( "test-kinng" ).ToStdString() );
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()