Finalize Python Frame
This commit is contained in:
parent
256f259627
commit
192fbfd5e5
|
@ -761,6 +761,8 @@ include( ${SWIG_USE_FILE} )
|
|||
# pybind11 is header-only, so include the subdir
|
||||
add_subdirectory(thirdparty/pybind11)
|
||||
|
||||
include_directories( SYSTEM ${PYBIND11_INCLUDE_DIR} )
|
||||
|
||||
set( PythonInterp_FIND_VERSION 3.6 )
|
||||
set( PythonLibs_FIND_VERSION 3.6 )
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ include_directories(
|
|||
${INC_AFTER}
|
||||
)
|
||||
|
||||
|
||||
if( NOT APPLE ) # windows and linux use openssl under curl
|
||||
find_package( OpenSSL REQUIRED )
|
||||
include_directories( SYSTEM ${OPENSSL_INCLUDE_DIR} )
|
||||
|
@ -484,6 +483,7 @@ target_link_libraries( common
|
|||
kimath
|
||||
kiplatform
|
||||
gal
|
||||
pybind11::embed
|
||||
${Boost_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES} # empty on Apple
|
||||
|
|
|
@ -102,28 +102,24 @@ BEGIN_EVENT_TABLE( EDA_BASE_FRAME, wxFrame )
|
|||
EVT_SYS_COLOUR_CHANGED( EDA_BASE_FRAME::onSystemColorChange )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType,
|
||||
const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
|
||||
long aStyle, const wxString& aFrameName, KIWAY* aKiway ) :
|
||||
wxFrame( aParent, wxID_ANY, aTitle, aPos, aSize, aStyle, aFrameName ),
|
||||
TOOLS_HOLDER(),
|
||||
KIWAY_HOLDER( aKiway, KIWAY_HOLDER::FRAME ),
|
||||
m_ident( aFrameType ),
|
||||
m_maximizeByDefault( false ),
|
||||
m_infoBar( nullptr ),
|
||||
m_settingsManager( nullptr ),
|
||||
m_fileHistory( nullptr ),
|
||||
m_hasAutoSave( false ),
|
||||
m_autoSaveState( false ),
|
||||
m_autoSaveInterval(-1 ),
|
||||
m_undoRedoCountMax( DEFAULT_MAX_UNDO_ITEMS ),
|
||||
m_userUnits( EDA_UNITS::MILLIMETRES ),
|
||||
m_isClosing( false ),
|
||||
m_isNonUserClose( false )
|
||||
|
||||
void EDA_BASE_FRAME::commonInit( FRAME_T aFrameType )
|
||||
{
|
||||
m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
|
||||
m_mruPath = PATHS::GetDefaultUserProjectsPath();
|
||||
m_frameSize = defaultSize( aFrameType );
|
||||
m_ident = aFrameType;
|
||||
m_maximizeByDefault = false;
|
||||
m_infoBar = nullptr;
|
||||
m_settingsManager = nullptr;
|
||||
m_fileHistory = nullptr;
|
||||
m_hasAutoSave = false;
|
||||
m_autoSaveState = false;
|
||||
m_autoSaveInterval = -1;
|
||||
m_undoRedoCountMax = DEFAULT_MAX_UNDO_ITEMS;
|
||||
m_userUnits = EDA_UNITS::MILLIMETRES;
|
||||
m_isClosing = false;
|
||||
m_isNonUserClose = false;
|
||||
m_autoSaveTimer = new wxTimer( this, ID_AUTO_SAVE_TIMER );
|
||||
m_mruPath = PATHS::GetDefaultUserProjectsPath();
|
||||
m_frameSize = defaultSize( aFrameType );
|
||||
|
||||
m_auimgr.SetArtProvider( new WX_AUI_DOCK_ART() );
|
||||
|
||||
|
@ -143,6 +139,25 @@ EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType,
|
|||
Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( EDA_BASE_FRAME::windowClosing ) );
|
||||
|
||||
initExitKey();
|
||||
|
||||
}
|
||||
|
||||
EDA_BASE_FRAME::EDA_BASE_FRAME( FRAME_T aFrameType, KIWAY* aKiway ) :
|
||||
wxFrame(),
|
||||
TOOLS_HOLDER(),
|
||||
KIWAY_HOLDER( aKiway, KIWAY_HOLDER::FRAME )
|
||||
{
|
||||
commonInit( aFrameType );
|
||||
}
|
||||
|
||||
EDA_BASE_FRAME::EDA_BASE_FRAME( wxWindow* aParent, FRAME_T aFrameType,
|
||||
const wxString& aTitle, const wxPoint& aPos, const wxSize& aSize,
|
||||
long aStyle, const wxString& aFrameName, KIWAY* aKiway ) :
|
||||
wxFrame( aParent, wxID_ANY, aTitle, aPos, aSize, aStyle, aFrameName ),
|
||||
TOOLS_HOLDER(),
|
||||
KIWAY_HOLDER( aKiway, KIWAY_HOLDER::FRAME )
|
||||
{
|
||||
commonInit( aFrameType );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <thread>
|
||||
|
||||
#include <eda_dde.h>
|
||||
#include <eda_draw_frame.h>
|
||||
#include <kiway_player.h>
|
||||
#include <id.h>
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
@ -45,7 +45,7 @@ static char client_ipc_buffer[IPC_BUF_SIZE];
|
|||
|
||||
/* Function to initialize a server socket
|
||||
*/
|
||||
void EDA_DRAW_FRAME::CreateServer( int service, bool local )
|
||||
void KIWAY_PLAYER::CreateServer( int service, bool local )
|
||||
{
|
||||
wxIPV4address addr;
|
||||
|
||||
|
@ -67,7 +67,7 @@ void EDA_DRAW_FRAME::CreateServer( int service, bool local )
|
|||
|
||||
/* Function called on every client request.
|
||||
*/
|
||||
void EDA_DRAW_FRAME::OnSockRequest( wxSocketEvent& evt )
|
||||
void KIWAY_PLAYER::OnSockRequest( wxSocketEvent& evt )
|
||||
{
|
||||
size_t len;
|
||||
wxSocketBase* sock = evt.GetSocket();
|
||||
|
@ -99,7 +99,7 @@ void EDA_DRAW_FRAME::OnSockRequest( wxSocketEvent& evt )
|
|||
|
||||
/* Function called when a connection is requested by a client.
|
||||
*/
|
||||
void EDA_DRAW_FRAME::OnSockRequestServer( wxSocketEvent& evt )
|
||||
void KIWAY_PLAYER::OnSockRequestServer( wxSocketEvent& evt )
|
||||
{
|
||||
wxSocketBase* socket;
|
||||
wxSocketServer* server = (wxSocketServer*) evt.GetSocket();
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include <bitmaps.h>
|
||||
#include <eda_item.h>
|
||||
|
|
|
@ -264,9 +264,9 @@ KIFACE* KIWAY::KiFACE( FACE_T aFaceId, bool doLoad )
|
|||
}
|
||||
else
|
||||
{
|
||||
KIFACE_GETTER_FUNC* getter = (KIFACE_GETTER_FUNC*) addr;
|
||||
KIFACE_GETTER_FUNC* ki_getter = (KIFACE_GETTER_FUNC*) addr;
|
||||
|
||||
KIFACE* kiface = getter( &m_kiface_version[aFaceId], KIFACE_VERSION, m_program );
|
||||
KIFACE* kiface = ki_getter( &m_kiface_version[aFaceId], KIFACE_VERSION, m_program );
|
||||
|
||||
// KIFACE_GETTER_FUNC function comment (API) says the non-NULL is unconditional.
|
||||
wxASSERT_MSG( kiface,
|
||||
|
|
|
@ -47,7 +47,8 @@ KIWAY_PLAYER::KIWAY_PLAYER( KIWAY* aKiway, wxWindow* aParent, FRAME_T aFrameType
|
|||
m_modal( false ),
|
||||
m_modal_loop( nullptr ),
|
||||
m_modal_resultant_parent( nullptr ),
|
||||
m_modal_ret_val( false )
|
||||
m_modal_ret_val( false ),
|
||||
m_socketServer( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -59,11 +60,11 @@ KIWAY_PLAYER::KIWAY_PLAYER( wxWindow* aParent, wxWindowID aId, const wxString& a
|
|||
m_modal( false ),
|
||||
m_modal_loop( nullptr ),
|
||||
m_modal_resultant_parent( nullptr ),
|
||||
m_modal_ret_val( false )
|
||||
m_modal_ret_val( false ),
|
||||
m_socketServer( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
KIWAY_PLAYER::~KIWAY_PLAYER() throw() {}
|
||||
|
||||
|
||||
|
|
|
@ -295,12 +295,12 @@ bool PGM_SINGLE_TOP::OnPgmInit()
|
|||
// i.e. they are single part link images so don't need to load a *.kiface.
|
||||
|
||||
// Get the getter, it is statically linked into this binary image.
|
||||
KIFACE_GETTER_FUNC* getter = &KIFACE_GETTER;
|
||||
KIFACE_GETTER_FUNC* ki_getter = &KIFACE_GETTER;
|
||||
|
||||
int kiface_version;
|
||||
|
||||
// Get the KIFACE.
|
||||
KIFACE* kiface = getter( &kiface_version, KIFACE_VERSION, this );
|
||||
KIFACE* kiface = ki_getter( &kiface_version, KIFACE_VERSION, this );
|
||||
|
||||
// Trick the KIWAY into thinking it loaded a KIFACE, by recording the KIFACE
|
||||
// in the KIWAY. It needs to be there for KIWAY::OnKiwayEnd() anyways.
|
||||
|
|
|
@ -106,6 +106,8 @@ public:
|
|||
const wxPoint& aPos, const wxSize& aSize, long aStyle,
|
||||
const wxString& aFrameName, KIWAY* aKiway );
|
||||
|
||||
EDA_BASE_FRAME( FRAME_T aFrameType, KIWAY* aKiway );
|
||||
|
||||
~EDA_BASE_FRAME();
|
||||
|
||||
/**
|
||||
|
@ -650,6 +652,11 @@ private:
|
|||
*/
|
||||
void windowClosing( wxCloseEvent& event );
|
||||
|
||||
/**
|
||||
* Collect common initialization functions used in all CTORs
|
||||
*/
|
||||
void commonInit( FRAME_T aFrameType );
|
||||
|
||||
wxWindow* findQuasiModalDialog();
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2007-2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
|
||||
* Copyright (C) 1992-2014 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||
* Copyright (C) 1992-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
|
||||
|
@ -42,6 +42,9 @@
|
|||
///< Eeschema listens on this port for commands from Pcbnew
|
||||
#define KICAD_SCH_PORT_SERVICE_NUMBER 4243
|
||||
|
||||
///< Scripting window listens for commands for other apps
|
||||
#define KICAD_PY_PORT_SERVICE_NUMBER 4244
|
||||
|
||||
|
||||
#define MSG_TO_PCB KICAD_PCB_PORT_SERVICE_NUMBER
|
||||
#define MSG_TO_SCH KICAD_SCH_PORT_SERVICE_NUMBER
|
||||
|
|
|
@ -191,14 +191,6 @@ public:
|
|||
*/
|
||||
virtual BASE_SCREEN* GetScreen() const { return m_currentScreen; }
|
||||
|
||||
/**
|
||||
* Execute a remote command sent via socket (to port KICAD_PCB_PORT_SERVICE_NUMBER,
|
||||
* currently 4242).
|
||||
*
|
||||
* Subclasses should override to implement actual command handlers.
|
||||
*/
|
||||
virtual void ExecuteRemoteCommand( const char* cmdline ){}
|
||||
|
||||
void EraseMsgBox();
|
||||
|
||||
void ReCreateMenuBar() override { }
|
||||
|
@ -346,11 +338,6 @@ public:
|
|||
*/
|
||||
virtual void DisplayGridMsg();
|
||||
|
||||
/* interprocess communication */
|
||||
void CreateServer( int service, bool local = true );
|
||||
void OnSockRequest( wxSocketEvent& evt );
|
||||
void OnSockRequestServer( wxSocketEvent& evt );
|
||||
|
||||
void LoadSettings( APP_SETTINGS_BASE* aCfg ) override;
|
||||
void SaveSettings( APP_SETTINGS_BASE* aCfg ) override;
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <kiway_holder.h>
|
||||
#include <eda_base_frame.h>
|
||||
|
||||
|
||||
class KIWAY;
|
||||
class PROJECT;
|
||||
struct KIFACE;
|
||||
|
@ -43,6 +42,9 @@ class KIWAY_EXPRESS;
|
|||
#define WX_EVENT_LOOP wxGUIEventLoop
|
||||
class WX_EVENT_LOOP;
|
||||
|
||||
class wxSocketServer;
|
||||
class wxSocketBase;
|
||||
|
||||
|
||||
/**
|
||||
* A wxFrame capable of the OpenProjectFiles function, meaning it can load a portion of
|
||||
|
@ -179,6 +181,20 @@ public:
|
|||
|
||||
void DismissModal( bool aRetVal, const wxString& aResult = wxEmptyString );
|
||||
|
||||
/* interprocess communication */
|
||||
void CreateServer( int service, bool local = true );
|
||||
void OnSockRequest( wxSocketEvent& evt );
|
||||
void OnSockRequestServer( wxSocketEvent& evt );
|
||||
|
||||
/**
|
||||
* Execute a remote command sent via socket (to port KICAD_PCB_PORT_SERVICE_NUMBER,
|
||||
* currently 4242).
|
||||
*
|
||||
* Subclasses should override to implement actual command handlers.
|
||||
*/
|
||||
virtual void ExecuteRemoteCommand( const char* cmdline ){}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/// event handler, routes to derivative specific virtual KiwayMailIn()
|
||||
|
@ -198,6 +214,9 @@ protected:
|
|||
wxString m_modal_string;
|
||||
bool m_modal_ret_val; // true if a selection was made
|
||||
|
||||
wxSocketServer* m_socketServer;
|
||||
std::vector<wxSocketBase*> m_sockets; ///< interprocess communication
|
||||
|
||||
#ifndef SWIG
|
||||
DECLARE_EVENT_TABLE()
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <wx/filename.h>
|
||||
#include <wx/gdicmn.h>
|
||||
|
||||
#include <pybind11/embed.h>
|
||||
|
||||
class wxSingleInstanceChecker;
|
||||
class wxApp;
|
||||
|
@ -329,6 +330,7 @@ protected:
|
|||
|
||||
/// Flag to indicate if the environment variable overwrite warning dialog should be shown.
|
||||
bool m_show_env_var_dialog;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1299,6 +1299,10 @@ void PCB_EDIT_FRAME::ScriptingConsoleEnableDisable()
|
|||
{
|
||||
frame = Kiway().Player( FRAME_PYTHON, true, this );
|
||||
|
||||
// If we received an error in the CTOR due to Python-ness, don't crash
|
||||
if( !frame )
|
||||
return;
|
||||
|
||||
if( !frame->IsVisible() )
|
||||
frame->Show( true );
|
||||
|
||||
|
|
|
@ -7,8 +7,6 @@ add_library( scripting STATIC
|
|||
${KIPYTHON_SRCS}
|
||||
)
|
||||
|
||||
add_subdirectory( pybind11 )
|
||||
|
||||
target_link_libraries( scripting
|
||||
${wxWidgets_LIBRARIES} # wxLogDebug, wxASSERT
|
||||
${Boost_LIBRARIES} # Because of the OPT types
|
||||
|
@ -32,6 +30,7 @@ target_include_directories( scripting PRIVATE
|
|||
# Setup the KIFACE
|
||||
add_library( scripting_kiface MODULE
|
||||
kicad_scripting_main.cpp
|
||||
kipython_frame.cpp
|
||||
${KIPYTHON_SRCS}
|
||||
)
|
||||
|
||||
|
@ -39,7 +38,7 @@ set_source_files_properties( kicad_scripting_main.cpp PROPERTIES
|
|||
# The KIFACE is in kicad_scripting_main.cpp, export it:
|
||||
COMPILE_DEFINITIONS "BUILD_KIWAY_DLL;COMPILING_DLL"
|
||||
)
|
||||
|
||||
|
||||
target_include_directories( scripting_kiface PRIVATE
|
||||
${PROJECT_SOURCE_DIR}/bitmaps_png/include
|
||||
${PROJECT_SOURCE_DIR}/include
|
||||
|
|
|
@ -15,17 +15,16 @@ import wx
|
|||
import sys
|
||||
import os
|
||||
|
||||
from wx.py import crust, editor, version, dispatcher
|
||||
from wx.py.editor import EditorNotebook
|
||||
from wx.py import crust, version, dispatcher
|
||||
|
||||
from .kicad_pyeditor import KiCadEditorNotebookFrame, KiCadEditorNotebook
|
||||
|
||||
import pcbnew
|
||||
|
||||
INTRO = "KiCad - Python Shell"
|
||||
|
||||
|
||||
class KiCadPyShell(editor.EditorNotebookFrame):
|
||||
|
||||
"""The KiCad Pythonshell based on wxPyShell"""
|
||||
class KiCadPyShell(KiCadEditorNotebookFrame):
|
||||
|
||||
def __init__(self, parent):
|
||||
KiCadEditorNotebookFrame.__init__(self, parent)
|
||||
|
||||
def _setup_startup(self):
|
||||
"""Initialise the startup script."""
|
||||
|
@ -58,7 +57,7 @@ class KiCadPyShell(editor.EditorNotebookFrame):
|
|||
|
||||
Called automatically by base class during init.
|
||||
"""
|
||||
self.notebook = EditorNotebook(parent=self)
|
||||
self.notebook = KiCadEditorNotebook(parent=self.parent)
|
||||
intro = 'Py %s' % version.VERSION
|
||||
import imp
|
||||
import builtins
|
||||
|
@ -81,11 +80,6 @@ class KiCadPyShell(editor.EditorNotebookFrame):
|
|||
self.autoSaveHistory = False
|
||||
self.LoadSettings()
|
||||
|
||||
# in case of wxPhoenix we may need to create a wxApp first and store it
|
||||
# to prevent removal by garbage collector
|
||||
if 'phoenix' in wx.PlatformInfo:
|
||||
self.theApp = wx.GetApp() or wx.App()
|
||||
|
||||
self.crust = crust.Crust(parent=self.notebook,
|
||||
intro=intro, locals=namespace,
|
||||
rootLabel="locals()",
|
||||
|
@ -94,9 +88,9 @@ class KiCadPyShell(editor.EditorNotebookFrame):
|
|||
|
||||
self.shell = self.crust.shell
|
||||
# Override the filling so that status messages go to the status bar.
|
||||
self.crust.filling.tree.setStatusText = self.SetStatusText
|
||||
self.crust.filling.tree.setStatusText = self.parent.SetStatusText
|
||||
# Override the shell so that status messages go to the status bar.
|
||||
self.shell.setStatusText = self.SetStatusText
|
||||
self.shell.setStatusText = self.parent.SetStatusText
|
||||
# Fix a problem with the sash shrinking to nothing.
|
||||
self.crust.filling.SetSashPosition(200)
|
||||
self.notebook.AddPage(page=self.crust, text='*Shell*', select=True)
|
||||
|
@ -115,7 +109,7 @@ class KiCadPyShell(editor.EditorNotebookFrame):
|
|||
"wxPython Version: %s\n" % wx.VERSION_STRING + \
|
||||
("\t(%s)\n" % ", ".join(wx.PlatformInfo[1:]))
|
||||
|
||||
dialog = wx.MessageDialog(self, text, title,
|
||||
dialog = wx.MessageDialog(self.parent, text, title,
|
||||
wx.OK | wx.ICON_INFORMATION)
|
||||
dialog.ShowModal()
|
||||
dialog.Destroy()
|
||||
|
@ -127,7 +121,7 @@ class KiCadPyShell(editor.EditorNotebookFrame):
|
|||
def LoadSettings(self):
|
||||
"""Load settings for the shell."""
|
||||
if self.config is not None:
|
||||
editor.EditorNotebookFrame.LoadSettings(self, self.config)
|
||||
KiCadEditorNotebookFrame.LoadSettings(self.parent, self.config)
|
||||
self.autoSaveSettings = \
|
||||
self.config.ReadBool('Options/AutoSaveSettings', False)
|
||||
self.execStartupScript = \
|
||||
|
@ -150,7 +144,7 @@ class KiCadPyShell(editor.EditorNotebookFrame):
|
|||
self.config.WriteBool('Options/AutoSaveSettings',
|
||||
self.autoSaveSettings)
|
||||
if self.autoSaveSettings or force:
|
||||
editor.EditorNotebookFrame.SaveSettings(self, self.config)
|
||||
KiCadEditorNotebookFrame.SaveSettings(self, self.config)
|
||||
|
||||
self.config.WriteBool('Options/AutoSaveHistory',
|
||||
self.autoSaveHistory)
|
||||
|
@ -209,7 +203,7 @@ class KiCadPyShell(editor.EditorNotebookFrame):
|
|||
d.Destroy()
|
||||
|
||||
|
||||
def makePcbnewShellWindow(parent=None):
|
||||
def makePcbnewShellWindow(parentid):
|
||||
"""
|
||||
Create a new Shell Window and return its handle.
|
||||
|
||||
|
@ -219,6 +213,6 @@ def makePcbnewShellWindow(parent=None):
|
|||
Returns:
|
||||
The handle to the new window.
|
||||
"""
|
||||
pyshell = KiCadPyShell(parent, id=-1, title=INTRO)
|
||||
pyshell.Show()
|
||||
return pyshell
|
||||
|
||||
parent = wx.FindWindowById( parentid )
|
||||
return KiCadPyShell(parent)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,16 +17,16 @@
|
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <eda_dde.h>
|
||||
#include <kiface_i.h>
|
||||
#include <kiface_ids.h>
|
||||
#include <kipython_frame.h>
|
||||
#include <kipython_settings.h>
|
||||
#include <kiway.h>
|
||||
#include <pgm_base.h>
|
||||
#include <python_scripting.h>
|
||||
#include <settings/settings_manager.h>
|
||||
|
||||
#include <kipython_settings.h>
|
||||
#include <python_scripting.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
//-----<KIFACE>-----------------------------------------------------------------
|
||||
|
@ -41,84 +41,15 @@ static struct IFACE : public KIFACE_I
|
|||
|
||||
wxWindow* CreateWindow( wxWindow* aParent, int aClassId, KIWAY* aKiway, int aCtlBits = 0 ) override
|
||||
{
|
||||
InitSettings( new KIPYTHON_SETTINGS );
|
||||
Pgm().GetSettingsManager().RegisterSettings( KifaceSettings() );
|
||||
KIPYTHON_FRAME* frame = new KIPYTHON_FRAME( aKiway, aParent );
|
||||
|
||||
|
||||
// passing window ids instead of pointers is because wxPython is not
|
||||
// exposing the needed c++ apis to make that possible.
|
||||
std::stringstream pcbnew_pyshell_one_step;
|
||||
pcbnew_pyshell_one_step << "import kicad_pyshell\n";
|
||||
pcbnew_pyshell_one_step << "import wx\n";
|
||||
pcbnew_pyshell_one_step << "\n";
|
||||
|
||||
// parent is actually *PCB_EDIT_FRAME
|
||||
if( aParent )
|
||||
if( Kiface().IsSingle() )
|
||||
{
|
||||
pcbnew_pyshell_one_step << "parent = wx.FindWindowById( " << aParent->GetId() << " )\n";
|
||||
pcbnew_pyshell_one_step << "newshell = kicad_pyshell.makePcbnewShellWindow( parent )\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
pcbnew_pyshell_one_step << "newshell = kicad_pyshell.makePcbnewShellWindow()\n";
|
||||
// only run this under single_top, not under a project manager.
|
||||
frame->CreateServer( KICAD_PY_PORT_SERVICE_NUMBER );
|
||||
}
|
||||
|
||||
pcbnew_pyshell_one_step << "newshell.SetName( \"KiCad Shell\" )\n";
|
||||
// return value goes into a "global". It's not actually global, but rather
|
||||
// the dict that is passed to PyRun_String
|
||||
pcbnew_pyshell_one_step << "retval = newshell.GetId()\n";
|
||||
|
||||
// As always, first grab the GIL
|
||||
PyLOCK lock;
|
||||
|
||||
// Now make a dictionary to serve as the global namespace when the code is
|
||||
// executed. Put a reference to the builtins module in it.
|
||||
|
||||
PyObject* globals = PyDict_New();
|
||||
PyObject* builtins = PyImport_ImportModule( "builtins" );
|
||||
|
||||
wxASSERT( builtins );
|
||||
|
||||
PyDict_SetItemString( globals, "__builtins__", builtins );
|
||||
Py_DECREF( builtins );
|
||||
|
||||
// Execute the code to make the makeWindow function we defined above
|
||||
PyObject* result = PyRun_String( pcbnew_pyshell_one_step.str().c_str(), Py_file_input,
|
||||
globals, globals );
|
||||
|
||||
// Was there an exception?
|
||||
if( !result )
|
||||
{
|
||||
PyErr_Print();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Py_DECREF( result );
|
||||
|
||||
result = PyDict_GetItemString( globals, "retval" );
|
||||
|
||||
if( !PyLong_Check( result ) )
|
||||
{
|
||||
wxLogError( "creation of scripting window didn't return a number" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const long windowId = PyLong_AsLong( result );
|
||||
|
||||
// It's important not to decref globals before extracting the window id.
|
||||
// If you do it early, globals, and the retval int it contains, may/will be garbage collected.
|
||||
// We do not need to decref result, because GetItemString returns a borrowed reference.
|
||||
Py_DECREF( globals );
|
||||
|
||||
wxWindow* window = wxWindow::FindWindowById( windowId );
|
||||
|
||||
if( !window )
|
||||
{
|
||||
wxLogError( "unable to find pyshell window with id %d", windowId );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return window;
|
||||
return frame;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,6 +111,8 @@ PGM_BASE* PgmOrNull()
|
|||
|
||||
bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )
|
||||
{
|
||||
InitSettings( new KIPYTHON_SETTINGS );
|
||||
Pgm().GetSettingsManager().RegisterSettings( KifaceSettings() );
|
||||
|
||||
ScriptingSetup();
|
||||
return start_common( aCtlBits );
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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 <frame_type.h>
|
||||
#include <kipython_frame.h>
|
||||
#include <kiway_player.h>
|
||||
#include <python_scripting.h>
|
||||
|
||||
#include <pybind11/embed.h>
|
||||
#include <sstream>
|
||||
#include <wx/wx.h>
|
||||
#include <pybind11/embed.h>
|
||||
|
||||
void KIPYTHON_FRAME::SetupPythonEditor()
|
||||
{
|
||||
|
||||
// passing window ids instead of pointers is because wxPython is not
|
||||
// exposing the needed c++ apis to make that possible.
|
||||
std::stringstream pcbnew_pyshell_one_step;
|
||||
pcbnew_pyshell_one_step << "import kicad_pyshell\n";
|
||||
pcbnew_pyshell_one_step << "newshell = kicad_pyshell.makePcbnewShellWindow( " << GetId() << " )\n";
|
||||
|
||||
// As always, first grab the GIL
|
||||
PyLOCK lock;
|
||||
|
||||
// Execute the code to make the makeWindow function we defined above
|
||||
PyRun_SimpleString( pcbnew_pyshell_one_step.str().c_str() );
|
||||
}
|
||||
|
||||
|
||||
void KIPYTHON_FRAME::redirectStdio()
|
||||
{
|
||||
// This is a helpful little tidbit to help debugging and such. It
|
||||
// redirects Python's stdout and stderr to a window that will popup
|
||||
// only on demand when something is printed, like a traceback.
|
||||
|
||||
PyLOCK lock;
|
||||
|
||||
using namespace pybind11::literals;
|
||||
int id = GetId();
|
||||
auto locals = pybind11::dict( "parent_id"_a= id );
|
||||
|
||||
pybind11::exec( R"(
|
||||
import sys
|
||||
import wx
|
||||
output = wx.PyOnDemandOutputWindow()
|
||||
sys.stderr = output
|
||||
parent = wx.Window.FindWindowById( parent_id )
|
||||
output.SetParent( parent )
|
||||
)", pybind11::globals(), locals );
|
||||
}
|
||||
|
||||
KIPYTHON_FRAME::KIPYTHON_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
||||
KIWAY_PLAYER( aKiway, aParent, FRAME_PYTHON, wxT( "KiPython" ), wxDefaultPosition,
|
||||
wxDefaultSize, KICAD_DEFAULT_DRAWFRAME_STYLE, wxT( "KiPython" ) )
|
||||
{
|
||||
m_stdio = 0;
|
||||
|
||||
CallAfter( [&](){ SetupPythonEditor(); } );
|
||||
|
||||
redirectStdio();
|
||||
}
|
||||
|
||||
|
||||
KIPYTHON_FRAME::~KIPYTHON_FRAME()
|
||||
{
|
||||
wxWindow* stdio_window = wxWindow::FindWindowById( m_stdio );
|
||||
|
||||
if( stdio_window )
|
||||
stdio_window->Close( true );
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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 SCRIPTING_KIPYTHON_FRAME_H_
|
||||
#define SCRIPTING_KIPYTHON_FRAME_H_
|
||||
|
||||
#include <kiway_player.h>
|
||||
|
||||
class wxWindow;
|
||||
class APP_SETTINGS_BASE;
|
||||
class KIWAY_EXPRESS;
|
||||
|
||||
class KIPYTHON_FRAME : public KIWAY_PLAYER
|
||||
{
|
||||
|
||||
|
||||
public:
|
||||
KIPYTHON_FRAME( KIWAY* aKiway, wxWindow* aParent );
|
||||
~KIPYTHON_FRAME() override;
|
||||
|
||||
void LoadSettings( APP_SETTINGS_BASE* aCfg ) override {}
|
||||
void SaveSettings( APP_SETTINGS_BASE* aCfg ) override {}
|
||||
|
||||
wxWindow* GetToolCanvas() const override { return nullptr;}
|
||||
|
||||
void ExecuteRemoteCommand( const char* cmdline ) override {}
|
||||
|
||||
void KiwayMailIn( KIWAY_EXPRESS& aEvent ) override {}
|
||||
void ProjectChanged() override {}
|
||||
|
||||
void SetupPythonEditor();
|
||||
private:
|
||||
|
||||
void redirectStdio();
|
||||
bool canCloseWindow( wxCloseEvent& aCloseEvent ) override { return true; }
|
||||
void doCloseWindow() override {}
|
||||
|
||||
long m_stdio;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* SCRIPTING_KIPYTHON_FRAME_H_ */
|
|
@ -54,17 +54,6 @@
|
|||
|
||||
extern "C" PyObject* PyInit__pcbnew( void );
|
||||
|
||||
#define EXTRA_PYTHON_MODULES 10 // this is the number of python
|
||||
// modules that we want to add into the list
|
||||
|
||||
|
||||
/* python inittab that links module names to module init functions
|
||||
* we will rebuild it to include the original python modules plus
|
||||
* our own ones
|
||||
*/
|
||||
|
||||
struct _inittab* SwigImportInittab;
|
||||
static int SwigNumModules = 0;
|
||||
|
||||
/// True if the wxPython scripting layer was successfully loaded.
|
||||
static bool wxPythonLoaded = false;
|
||||
|
@ -75,70 +64,6 @@ bool IsWxPythonLoaded()
|
|||
return wxPythonLoaded;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a name + initfuction to our SwigImportInittab
|
||||
*/
|
||||
|
||||
static void swigAddModule( const char* name, PyObject* (* initfunc)() )
|
||||
{
|
||||
SwigImportInittab[SwigNumModules].name = (char*) name;
|
||||
SwigImportInittab[SwigNumModules].initfunc = initfunc;
|
||||
SwigNumModules++;
|
||||
SwigImportInittab[SwigNumModules].name = (char*) 0;
|
||||
SwigImportInittab[SwigNumModules].initfunc = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the builtin python modules
|
||||
*/
|
||||
static void swigAddBuiltin()
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
/* discover the length of the pyimport inittab */
|
||||
while( PyImport_Inittab[i].name )
|
||||
i++;
|
||||
|
||||
/* allocate memory for the python module table */
|
||||
SwigImportInittab = (struct _inittab*) malloc(
|
||||
sizeof( struct _inittab ) * ( i + EXTRA_PYTHON_MODULES ) );
|
||||
|
||||
/* copy all pre-existing python modules into our newly created table */
|
||||
i = 0;
|
||||
|
||||
while( PyImport_Inittab[i].name )
|
||||
{
|
||||
swigAddModule( PyImport_Inittab[i].name, PyImport_Inittab[i].initfunc );
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the internal modules to the python scripting so they will be available to the scripts.
|
||||
*/
|
||||
static void swigAddModules()
|
||||
{
|
||||
swigAddModule( "_pcbnew", PyInit__pcbnew );
|
||||
|
||||
// finally it seems better to include all in just one module
|
||||
// but in case we needed to include any other modules,
|
||||
// it must be done like this:
|
||||
// swigAddModule( "_kicad", init_kicad );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Switch the python module table to the Pcbnew built one.
|
||||
*/
|
||||
static void swigSwitchPythonBuiltin()
|
||||
{
|
||||
PyImport_Inittab = SwigImportInittab;
|
||||
}
|
||||
|
||||
|
||||
PyThreadState* g_PythonMainTState;
|
||||
|
||||
|
||||
|
@ -245,9 +170,7 @@ bool InitPythonScripting( const char* aStockScriptingPath, const char* aUserScri
|
|||
int retv;
|
||||
char cmd[1024];
|
||||
|
||||
swigAddBuiltin(); // add builtin functions
|
||||
swigAddModules(); // add our own modules
|
||||
swigSwitchPythonBuiltin(); // switch the python builtin modules to our new list
|
||||
PyImport_AppendInittab( "_pcbnew", PyInit__pcbnew );
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Under vcpkg/msvc, we need to explicitly set the python home
|
||||
|
@ -266,18 +189,16 @@ bool InitPythonScripting( const char* aStockScriptingPath, const char* aUserScri
|
|||
Py_SetPythonHome( pyHome.GetFullPath().c_str() );
|
||||
}
|
||||
#endif
|
||||
//
|
||||
// Py_Initialize();
|
||||
pybind11::initialize_interpreter();
|
||||
|
||||
Py_Initialize();
|
||||
PySys_SetArgv( Pgm().App().argc, Pgm().App().argv );
|
||||
// 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
|
||||
|
||||
#if defined( DEBUG )
|
||||
RedirectStdio();
|
||||
#endif
|
||||
|
||||
wxPythonLoaded = true;
|
||||
|
||||
// Save the current Python thread state and release the
|
||||
|
@ -374,7 +295,7 @@ static void RunPythonMethodWithReturnedString( const char* aMethodName, wxString
|
|||
void FinishPythonScripting()
|
||||
{
|
||||
PyEval_RestoreThread( g_PythonMainTState );
|
||||
Py_Finalize();
|
||||
pybind11::finalize_interpreter();
|
||||
}
|
||||
|
||||
|
||||
|
@ -426,25 +347,6 @@ void UpdatePythonEnvVar( const wxString& aVar, const wxString& aValue )
|
|||
wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, cmd );
|
||||
}
|
||||
|
||||
void RedirectStdio()
|
||||
{
|
||||
// This is a helpful little tidbit to help debugging and such. It
|
||||
// redirects Python's stdout and stderr to a window that will popup
|
||||
// only on demand when something is printed, like a traceback.
|
||||
const char* python_redirect =
|
||||
"import sys\n"
|
||||
"import wx\n"
|
||||
"output = wx.PyOnDemandOutputWindow()\n"
|
||||
"sys.stderr = output\n";
|
||||
|
||||
PyLOCK lock;
|
||||
|
||||
int retv = PyRun_SimpleString( python_redirect );
|
||||
|
||||
if( retv != 0 )
|
||||
wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, python_redirect );
|
||||
}
|
||||
|
||||
|
||||
wxString PyStringToWx( PyObject* aString )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue