Commit 89dd0748 authored by Miguel Angel Ajo's avatar Miguel Angel Ajo

pcbnew scripting: cleanup, renamed KICAD_SCRIPTING_EXPERIMENT to...

pcbnew scripting: cleanup, renamed KICAD_SCRIPTING_EXPERIMENT to KICAD_SCRIPTING_WXPYTHON, now every flavour compiles
parent b0881d8e
...@@ -56,8 +56,8 @@ option(KICAD_SCRIPTING_MODULES ...@@ -56,8 +56,8 @@ option(KICAD_SCRIPTING_MODULES
"set this option ON to build kicad modules that can be used from scripting languages" "set this option ON to build kicad modules that can be used from scripting languages"
) )
option(KICAD_SCRIPTING_EXPERIMENT option(KICAD_SCRIPTING_WXPYTHON
"set this option ON to build Edwin's TEST code with linking to python and pycrust shell" "set this option ON to build wxpython implementation for wx interface building in python and py.shell"
) )
...@@ -140,11 +140,11 @@ if(KICAD_SCRIPTING_MODULES) ...@@ -140,11 +140,11 @@ if(KICAD_SCRIPTING_MODULES)
add_definitions(-DKICAD_SCRIPTING_MODULES) add_definitions(-DKICAD_SCRIPTING_MODULES)
endif(KICAD_SCRIPTING_MODULES) endif(KICAD_SCRIPTING_MODULES)
if(KICAD_SCRIPTING_EXPERIMENT) if(KICAD_SCRIPTING_WXPYTHON)
add_definitions(-DKICAD_SCRIPTING_EXPERIMENT) add_definitions(-DKICAD_SCRIPTING_WXPYTHON)
endif(KICAD_SCRIPTING_EXPERIMENT) endif(KICAD_SCRIPTING_WXPYTHON)
if(USE_WX_GRAPHICS_CONTEXT) if(USE_WX_GRAPHICS_CONTEXT)
add_definitions(-DUSE_WX_GRAPHICS_CONTEXT) add_definitions(-DUSE_WX_GRAPHICS_CONTEXT)
......
...@@ -86,6 +86,11 @@ class PCB_EDIT_FRAME : public PCB_BASE_FRAME ...@@ -86,6 +86,11 @@ class PCB_EDIT_FRAME : public PCB_BASE_FRAME
protected: protected:
#ifdef KICAD_SCRIPTING_WXPYTHON
// Panel used to let user talk with internal scripting
wxWindow* m_pythonPanel;
#endif
PCB_LAYER_WIDGET* m_Layers; PCB_LAYER_WIDGET* m_Layers;
DRC* m_drc; ///< the DRC controller, see drc.cpp DRC* m_drc; ///< the DRC controller, see drc.cpp
......
...@@ -1074,6 +1074,19 @@ public: ...@@ -1074,6 +1074,19 @@ public:
return *this; return *this;
} }
/**
* Function ScriptingToolbarPane
* Change *this to a scripting toolbar for KiCad.
*/
EDA_PANEINFO& ScriptingToolbarPane()
{
CloseButton( false );
Floatable( true );
Resizable( true );
return *this;
}
}; };
#endif // WXSTRUCT_H_ #endif // WXSTRUCT_H_
...@@ -53,6 +53,9 @@ ...@@ -53,6 +53,9 @@
#include <dialog_SVG_print.h> #include <dialog_SVG_print.h>
#include <dialog_helpers.h> #include <dialog_helpers.h>
#ifdef KICAD_SCRIPTING
#include <python_scripting.h>
#endif
// Keys used in read/write config // Keys used in read/write config
#define OPTKEY_DEFAULT_LINEWIDTH_VALUE wxT( "PlotLineWidth" ) #define OPTKEY_DEFAULT_LINEWIDTH_VALUE wxT( "PlotLineWidth" )
...@@ -280,7 +283,9 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, ...@@ -280,7 +283,9 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title,
m_RecordingMacros = -1; m_RecordingMacros = -1;
m_microWaveToolBar = NULL; m_microWaveToolBar = NULL;
m_autoPlaceModeId = 0; m_autoPlaceModeId = 0;
#ifdef KICAD_SCRIPTING_WXPYTHON
m_pythonPanel = NULL;
#endif
for ( int i = 0; i < 10; i++ ) for ( int i = 0; i < 10; i++ )
m_Macros[i].m_Record.clear(); m_Macros[i].m_Record.clear();
...@@ -397,6 +402,22 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title, ...@@ -397,6 +402,22 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title,
m_auimgr.AddPane( m_messagePanel, m_auimgr.AddPane( m_messagePanel,
wxAuiPaneInfo( mesg ).Name( wxT( "MsgPanel" ) ).Bottom().Layer(10) ); wxAuiPaneInfo( mesg ).Name( wxT( "MsgPanel" ) ).Bottom().Layer(10) );
#ifdef KICAD_SCRIPTING_WXPYTHON
// Add the scripting panel
EDA_PANEINFO pythonAuiInfo;
pythonAuiInfo.ScriptingToolbarPane();
pythonAuiInfo.Caption( wxT( "Python Scripting" ) );
pythonAuiInfo.MinSize( wxSize( 200, 100 ) );
pythonAuiInfo.BestSize( wxSize( GetClientSize().x/2, 200 ) );
m_pythonPanel = CreatePythonShellWindow( this );
m_auimgr.AddPane( m_pythonPanel,
pythonAuiInfo.Name( wxT( "PythonPanel" ) ).Bottom().Layer(9) );
#endif
ReFillLayerWidget(); // this is near end because contents establish size ReFillLayerWidget(); // this is near end because contents establish size
m_Layers->ReFillRender(); // Update colors in Render after the config is read m_Layers->ReFillRender(); // Update colors in Render after the config is read
......
...@@ -102,34 +102,6 @@ void EDA_APP::MacOpenFile( const wxString& fileName ) ...@@ -102,34 +102,6 @@ void EDA_APP::MacOpenFile( const wxString& fileName )
frame->LoadOnePcbFile( fileName, false ); frame->LoadOnePcbFile( fileName, false );
} }
#ifdef KICAD_SCRIPTING_EXPERIMENT
class MyFrame : public wxFrame {
public:
MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
void RedirectStdio();
wxWindow* DoPythonStuff(wxWindow* parent);
void OnExit(wxCommandEvent& event);
void OnPyFrame(wxCommandEvent& event);
void ScriptingSetPcbEditFrame(PCB_EDIT_FRAME *aPCBEdaFrame);
private:
DECLARE_EVENT_TABLE()
PCB_EDIT_FRAME *PcbEditFrame ;
};
enum
{
ID_EXIT=1001,
ID_PYFRAME
};
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_EXIT, MyFrame::OnExit)
EVT_MENU(ID_PYFRAME, MyFrame::OnPyFrame)
END_EVENT_TABLE()
#endif
bool EDA_APP::OnInit() bool EDA_APP::OnInit()
{ {
wxFileName fn; wxFileName fn;
...@@ -235,17 +207,10 @@ Changing extension to .brd." ), GetChars( fn.GetFullPath() ) ); ...@@ -235,17 +207,10 @@ Changing extension to .brd." ), GetChars( fn.GetFullPath() ) );
*/ */
frame->SetFocus(); frame->SetFocus();
frame->GetCanvas()->SetFocus(); frame->GetCanvas()->SetFocus();
#ifdef KICAD_SCRIPTING_EXPERIMENT
MyFrame *zz = new MyFrame(_T("Embedded wxPython Test"),wxDefaultPosition, wxSize(700, 600));
zz->Show(true);
zz->ScriptingSetPcbEditFrame(frame); // make the frame available to my python thing
// now to find a way to use it for something useful
#endif
return true; return true;
} }
#if 0 #if 0
// for some reason KiCad classes do not implement OnExit // for some reason KiCad classes do not implement OnExit
// if I add it in the declaration, I need to fix it in every application // if I add it in the declaration, I need to fix it in every application
...@@ -256,194 +221,12 @@ int EDA_APP::OnExit() { ...@@ -256,194 +221,12 @@ int EDA_APP::OnExit() {
// wxPython will do its own cleanup as part of that process. This is done // wxPython will do its own cleanup as part of that process. This is done
// in OnExit instead of ~MyApp because OnExit is only called if OnInit is // in OnExit instead of ~MyApp because OnExit is only called if OnInit is
// successful. // successful.
#if KICAD_SCRIPTING_EXPERIMENT #if KICAD_SCRIPTING_WXPYTHON
pcbnewFinishPythonScripting(); pcbnewFinishPythonScripting();
#endif #endif
return 0; return 0;
} }
#endif
#ifdef KICAD_SCRIPTING_EXPERIMENT
MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame(NULL, -1, title, pos, size,
wxDEFAULT_FRAME_STYLE|wxNO_FULL_REPAINT_ON_RESIZE)
{
// SetIcon(wxICON(mondrian));
wxMenuBar* mbar = new wxMenuBar;
wxMenu* menu = new wxMenu;
menu->Append(ID_PYFRAME, _T("Make wx&Python frame"));
menu->AppendSeparator();
menu->Append(ID_EXIT, _T("&Close Frame\tAlt-X"));
mbar->Append(menu, _T("&File"));
SetMenuBar(mbar);
CreateStatusBar();
RedirectStdio();
// Make some child windows from C++
wxSplitterWindow* sp = new wxSplitterWindow(this, -1);
wxPanel* p1 = new wxPanel(sp, -1, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER);
new wxStaticText(p1, -1,
_T("The frame, menu, splitter, this panel and this text were created in C++..."),
wxPoint(10,10));
// And get a panel from Python
wxWindow* p2 = DoPythonStuff(sp);
if (p2)
sp->SplitHorizontally(p1, p2, GetClientSize().y/4);
}
void MyFrame::OnExit(wxCommandEvent& event)
{
Close();
}
void MyFrame::ScriptingSetPcbEditFrame(PCB_EDIT_FRAME *aPCBEdaFrame)
{
PcbEditFrame = aPCBEdaFrame;
}
//----------------------------------------------------------------------
// This is where the fun begins...
#endif
const char* python_code1 = "\
import wx\n\
f = wx.Frame(None, -1, 'Hello from wxPython!', size=(250, 150))\n\
f.Show()\n\
";
void MyFrame::OnPyFrame(wxCommandEvent& event)
{
// For simple Python code that doesn't have to interact with the
// C++ code in any way, you can execute it with PyRun_SimpleString.
// First, whenever you do anything with Python objects or code, you
// *MUST* aquire the Global Interpreter Lock and block other
// Python threads from running.
wxPyBlock_t blocked = wxPyBeginBlockThreads();
// Execute the code in the __main__ module
PyRun_SimpleString(python_code1);
// Finally, release the GIL and let other Python threads run.
wxPyEndBlockThreads(blocked);
}
void MyFrame::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.stdin = sys.stderr = output\n";
wxPyBlock_t blocked = wxPyBeginBlockThreads();
PyRun_SimpleString(python_redirect);
wxPyEndBlockThreads(blocked);
}
wxWindow* MyFrame::DoPythonStuff(wxWindow* parent)
{
const char* pycrust_panel = "\
import wx\n\
from wx.py import shell, version\n\
\n\
class MyPanel(wx.Panel):\n\
\tdef __init__(self, parent):\n\
\t\twx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)\n\
\t\t\n\
\t\ttext = wx.StaticText(self, -1,\n\
\t\t\t\t\"Everything on this side of the splitter comes from Python.\")\n\
\t\t\n\
\t\tintro = \"Welcome To PyCrust %s - KiCad's Python Shell\" % version.VERSION\n\
\t\tpycrust = shell.Shell(self, -1, introText=intro)\n\
\t\t\n\
\t\tsizer = wx.BoxSizer(wx.VERTICAL)\n\n\
\t\tsizer.Add(text, 0, wx.EXPAND|wx.ALL, 10)\n\n\
\t\tsizer.Add(pycrust, 1, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 10)\n\n\
\t\tself.SetSizer(sizer)\n\n\
\n\
def makeWindow(parent):\n\
win = MyPanel(parent)\n\
return win\n\
";
// More complex embedded situations will require passing C++ objects to
// Python and/or returning objects from Python to be used in C++. This
// sample shows one way to do it. NOTE: The above code could just have
// easily come from a file, or the whole thing could be in the Python
// module that is imported and manipulated directly in this C++ code. See
// the Python API for more details.
wxWindow* window = NULL;
PyObject* result;
// As always, first grab the GIL
wxPyBlock_t blocked = wxPyBeginBlockThreads();
// Now make a dictionary to serve as the global namespace when the code is
// executed. Put a reference to the builtins module in it. (Yes, the
// names are supposed to be different, I don't know why...)
PyObject* globals = PyDict_New();
PyObject* builtins = PyImport_ImportModule("__builtin__");
PyDict_SetItemString(globals, "__builtins__", builtins);
Py_DECREF(builtins);
// Execute the code to make the makeWindow function
result = PyRun_String(pycrust_panel, Py_file_input, globals, globals);
// Was there an exception?
if (! result) {
PyErr_Print();
wxPyEndBlockThreads(blocked);
return NULL;
}
Py_DECREF(result);
// Now there should be an object named 'makeWindow' in the dictionary that
// we can grab a pointer to:
PyObject* func = PyDict_GetItemString(globals, "makeWindow");
wxASSERT(PyCallable_Check(func));
// Now build an argument tuple and call the Python function. Notice the
// use of another wxPython API to take a wxWindows object and build a
// wxPython object that wraps it.
PyObject* arg = wxPyMake_wxObject(parent, false);
wxASSERT(arg != NULL);
PyObject* tuple = PyTuple_New(1);
PyTuple_SET_ITEM(tuple, 0, arg);
result = PyEval_CallObject(func, tuple);
// Was there an exception?
if (! result)
PyErr_Print();
else {
// Otherwise, get the returned window out of Python-land and
// into C++-ville...
bool success = wxPyConvertSwigPtr(result, (void**)&window, _T("wxWindow"));
(void)success;
wxASSERT_MSG(success, _T("Returned object was not a wxWindow!"));
Py_DECREF(result);
}
// Release the python objects we still have
Py_DECREF(globals);
Py_DECREF(tuple);
// Finally, after all Python stuff is done, release the GIL
wxPyEndBlockThreads(blocked);
return window;
}
#endif
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
*/ */
#include "pcbnew_footprint_wizards.h" #include "pcbnew_footprint_wizards.h"
#include <wx/wxPython/wxPython.h> #include <python_scripting.h>
#include <stdio.h> #include <stdio.h>
PYTHON_FOOTPRINT_WIZARD::PYTHON_FOOTPRINT_WIZARD(PyObject *aWizard) PYTHON_FOOTPRINT_WIZARD::PYTHON_FOOTPRINT_WIZARD(PyObject *aWizard)
...@@ -29,7 +30,7 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr ...@@ -29,7 +30,7 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr
{ {
PyObject *result; PyObject *result;
wxPyBlock_t blocked = wxPyBeginBlockThreads(); PY_BLOCK_THREADS( blocked );
result = PyObject_CallObject( pFunc, aArglist ); result = PyObject_CallObject( pFunc, aArglist );
...@@ -42,7 +43,7 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr ...@@ -42,7 +43,7 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr
printf ( " : %s\n", PyString_AsString( PyObject_Str(b) ) ); printf ( " : %s\n", PyString_AsString( PyObject_Str(b) ) );
} }
wxPyEndBlockThreads( blocked ); PY_UNBLOCK_THREADS( blocked );
if ( result ) if ( result )
{ {
...@@ -70,12 +71,12 @@ wxString PYTHON_FOOTPRINT_WIZARD::CallRetStrMethod( const char* aMethod, PyObjec ...@@ -70,12 +71,12 @@ wxString PYTHON_FOOTPRINT_WIZARD::CallRetStrMethod( const char* aMethod, PyObjec
PyObject *result = CallMethod( aMethod, aArglist ); PyObject *result = CallMethod( aMethod, aArglist );
if ( result ) if ( result )
{ {
wxPyBlock_t blocked = wxPyBeginBlockThreads(); PY_BLOCK_THREADS( blocked );
const char *str_res = PyString_AsString( result ); const char *str_res = PyString_AsString( result );
ret = wxString::FromUTF8( str_res ); ret = wxString::FromUTF8( str_res );
Py_DECREF( result ); Py_DECREF( result );
wxPyEndBlockThreads( blocked ); PY_UNBLOCK_THREADS( blocked );
} }
return ret; return ret;
} }
...@@ -99,7 +100,8 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod ...@@ -99,7 +100,8 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod
return ret; return ret;
} }
wxPyBlock_t blocked = wxPyBeginBlockThreads(); PY_BLOCK_THREADS( blocked );
int list_size = PyList_Size( result ); int list_size = PyList_Size( result );
for ( int n=0; n<list_size; n++ ) for ( int n=0; n<list_size; n++ )
...@@ -112,7 +114,8 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod ...@@ -112,7 +114,8 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod
} }
Py_DECREF( result ); Py_DECREF( result );
wxPyEndBlockThreads( blocked );
PY_UNBLOCK_THREADS( blocked );
} }
...@@ -148,12 +151,13 @@ int PYTHON_FOOTPRINT_WIZARD::GetNumParameterPages() ...@@ -148,12 +151,13 @@ int PYTHON_FOOTPRINT_WIZARD::GetNumParameterPages()
{ {
if ( !PyInt_Check( result ) ) if ( !PyInt_Check( result ) )
return -1; return -1;
wxPyBlock_t blocked = wxPyBeginBlockThreads();
PY_BLOCK_THREADS( blocked );
ret = PyInt_AsLong( result ); ret = PyInt_AsLong( result );
Py_DECREF( result ); Py_DECREF( result );
wxPyEndBlockThreads( blocked ); PY_UNBLOCK_THREADS( blocked );
} }
return ret; return ret;
} }
...@@ -171,13 +175,13 @@ wxString PYTHON_FOOTPRINT_WIZARD::GetParameterPageName( int aPage ) ...@@ -171,13 +175,13 @@ wxString PYTHON_FOOTPRINT_WIZARD::GetParameterPageName( int aPage )
if ( result ) if ( result )
{ {
wxPyBlock_t blocked = wxPyBeginBlockThreads(); PY_BLOCK_THREADS( blocked );
const char *str_res = PyString_AsString( result ); const char *str_res = PyString_AsString( result );
ret = wxString::FromUTF8( str_res ); ret = wxString::FromUTF8( str_res );
Py_DECREF( result ); Py_DECREF( result );
wxPyEndBlockThreads( blocked ); PY_UNBLOCK_THREADS( blocked );
} }
return ret; return ret;
} }
...@@ -295,7 +299,7 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule() ...@@ -295,7 +299,7 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule()
if (!result) if (!result)
return NULL; return NULL;
wxPyBlock_t blocked = wxPyBeginBlockThreads(); PY_BLOCK_THREADS( blocked );
obj = PyObject_GetAttrString( result, "this" ); obj = PyObject_GetAttrString( result, "this" );
...@@ -310,7 +314,7 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule() ...@@ -310,7 +314,7 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule()
*/ */
PyErr_Print(); PyErr_Print();
} }
wxPyEndBlockThreads( blocked ); PY_UNBLOCK_THREADS( blocked );
MODULE *mod = PyModule_to_MODULE( obj ); MODULE *mod = PyModule_to_MODULE( obj );
......
...@@ -28,9 +28,16 @@ ...@@ -28,9 +28,16 @@
*/ */
#include <python_scripting.h> #include <python_scripting.h>
#include <wx/wxPython/wxPython.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __GNUG__
#pragma implementation
#endif
#include <fctsys.h>
#include <wxstruct.h>
#include <common.h>
#include <colors.h>
/* init functions defined by swig */ /* init functions defined by swig */
...@@ -127,6 +134,8 @@ bool pcbnewInitPythonScripting() ...@@ -127,6 +134,8 @@ bool pcbnewInitPythonScripting()
swigSwitchPythonBuiltin(); // switch the python builtin modules to our new list swigSwitchPythonBuiltin(); // switch the python builtin modules to our new list
Py_Initialize(); Py_Initialize();
#ifdef KICAD_SCRIPTING_WXPYTHON
PyEval_InitThreads(); PyEval_InitThreads();
// Load the wxPython core API. Imports the wx._core_ module and sets a // Load the wxPython core API. Imports the wx._core_ module and sets a
...@@ -146,21 +155,140 @@ bool pcbnewInitPythonScripting() ...@@ -146,21 +155,140 @@ bool pcbnewInitPythonScripting()
// load pcbnew inside python, and load all the user plugins, TODO: add system wide plugins // load pcbnew inside python, and load all the user plugins, TODO: add system wide plugins
wxPyBlock_t blocked = wxPyBeginBlockThreads(); PY_BLOCK_THREADS( blocked );
#endif
PyRun_SimpleString( "import sys\n" PyRun_SimpleString( "import sys\n"
"sys.path.append(\".\")\n" "sys.path.append(\".\")\n"
"import pcbnew\n" "import pcbnew\n"
"pcbnew.LoadPlugins()" "pcbnew.LoadPlugins()"
); );
wxPyEndBlockThreads(blocked);
PY_UNBLOCK_THREADS( blocked );
return true; return true;
} }
void pcbnewFinishPythonScripting() void pcbnewFinishPythonScripting()
{ {
#ifdef KICAD_SCRIPTING_WXPYTHON
wxPyEndAllowThreads(g_PythonMainTState); wxPyEndAllowThreads(g_PythonMainTState);
#endif
Py_Finalize(); Py_Finalize();
} }
#ifdef KICAD_SCRIPTING_WXPYTHON
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\
c sys.stderr = output\n";
PY_BLOCK_THREADS( blocked );
PyRun_SimpleString( python_redirect );
PY_UNBLOCK_THREADS( blocked );
}
wxWindow* CreatePythonShellWindow(wxWindow* parent)
{
const char* pycrust_panel = "\
import wx\n\
from wx.py import shell, version\n\
\n\
class PyCrustPanel(wx.Panel):\n\
\tdef __init__(self, parent):\n\
\t\twx.Panel.__init__(self, parent, -1, style=wx.SUNKEN_BORDER)\n\
\t\t\n\
\t\t\n\
\t\tintro = \"Welcome To PyCrust %s - KiCAD Python Shell\" % version.VERSION\n\
\t\tpycrust = shell.Shell(self, -1, introText=intro)\n\
\t\t\n\
\t\tsizer = wx.BoxSizer(wx.VERTICAL)\n\n\
\t\tsizer.Add(pycrust, 1, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 10)\n\n\
\t\tself.SetSizer(sizer)\n\n\
\n\
def makeWindow(parent):\n\
win = PyCrustPanel(parent)\n\
return win\n\
";
wxWindow* window = NULL;
PyObject* result;
// As always, first grab the GIL
PY_BLOCK_THREADS( blocked );
// 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( "__builtin__" );
PyDict_SetItemString( globals, "__builtins__", builtins );
Py_DECREF(builtins);
// Execute the code to make the makeWindow function we defined above
result = PyRun_String( pycrust_panel, Py_file_input, globals, globals );
// Was there an exception?
if ( !result )
{
PyErr_Print();
PY_UNBLOCK_THREADS( blocked );
return NULL;
}
Py_DECREF(result);
// Now there should be an object named 'makeWindow' in the dictionary that
// we can grab a pointer to:
PyObject* func = PyDict_GetItemString( globals, "makeWindow" );
wxASSERT( PyCallable_Check( func ) );
// Now build an argument tuple and call the Python function. Notice the
// use of another wxPython API to take a wxWindows object and build a
// wxPython object that wraps it.
PyObject* arg = wxPyMake_wxObject( parent, false );
wxASSERT( arg != NULL );
PyObject* tuple = PyTuple_New( 1 );
PyTuple_SET_ITEM( tuple, 0, arg );
result = PyEval_CallObject( func, tuple );
// Was there an exception?
if ( !result )
PyErr_Print();
else
{
// Otherwise, get the returned window out of Python-land and
// into C++-ville...
bool success = wxPyConvertSwigPtr(result, (void**)&window, _T("wxWindow") );
(void)success;
wxASSERT_MSG(success, _T("Returned object was not a wxWindow!") );
Py_DECREF(result);
}
// Release the python objects we still have
Py_DECREF( globals );
Py_DECREF( tuple );
// Finally, after all Python stuff is done, release the GIL
PY_UNBLOCK_THREADS( blocked );
return window;
}
#endif
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
#include <Python.h> #include <Python.h>
#ifndef NO_WXPYTHON_EXTENSION_HEADERS #ifndef NO_WXPYTHON_EXTENSION_HEADERS
#ifdef KICAD_SCRIPTING_WXPYTHON
#include <wx/wxPython/wxPython.h> #include <wx/wxPython/wxPython.h>
#endif #endif
#endif
/* Function pcbnewInitPythonScripting /* Function pcbnewInitPythonScripting
...@@ -23,4 +25,21 @@ ...@@ -23,4 +25,21 @@
bool pcbnewInitPythonScripting(); bool pcbnewInitPythonScripting();
void pcbnewFinishPythonScripting(); void pcbnewFinishPythonScripting();
#ifdef KICAD_SCRIPTING_WXPYTHON
void RedirectStdio();
wxWindow* CreatePythonShellWindow(wxWindow* parent);
#define PY_BLOCK_THREADS(name) wxPyBlock_t name = wxPyBeginBlockThreads()
#define PY_UNBLOCK_THREADS(name) wxPyEndBlockThreads(name)
#else
#define PY_BLOCK_THREADS(name)
#define PY_UNBLOCK_THREADS(name)
#endif
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment