Commit 4d2def35 authored by Miguel Angel Ajo's avatar Miguel Angel Ajo

scripting + pcbnew: Merged with scripting branch, now it supports...

scripting + pcbnew: Merged with scripting branch, now it supports -DKICAD_SCRIPTING_WXPYTHON for full wx integration with python
parents ef39c5f3 89dd0748
...@@ -56,7 +56,10 @@ option(KICAD_SCRIPTING_MODULES ...@@ -56,7 +56,10 @@ 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_WXPYTHON
"set this option ON to build wxpython implementation for wx interface building in python and py.shell"
)
#Set version option (stable or testing) #Set version option (stable or testing)
...@@ -136,7 +139,12 @@ endif(KICAD_SCRIPTING) ...@@ -136,7 +139,12 @@ endif(KICAD_SCRIPTING)
if(KICAD_SCRIPTING_MODULES) 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_WXPYTHON)
add_definitions(-DKICAD_SCRIPTING_WXPYTHON)
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)
...@@ -248,6 +256,19 @@ if(WIN32 AND USE_WX_GRAPHICS_CONTEXT) ...@@ -248,6 +256,19 @@ if(WIN32 AND USE_WX_GRAPHICS_CONTEXT)
check_find_package_result(GDI_PLUS_FOUND "GDI+") check_find_package_result(GDI_PLUS_FOUND "GDI+")
endif(WIN32 AND USE_WX_GRAPHICS_CONTEXT) endif(WIN32 AND USE_WX_GRAPHICS_CONTEXT)
# Find Python and other scripting resources
if (KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES)
execute_process(COMMAND python2 -c "import sys;print\"%s.%s\"%sys.version_info[0:2]" OUTPUT_VARIABLE PYTHON_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
set(PYTHON_DEST "lib/python${PYTHON_VERSION}/dist-packages" )
find_package(PythonLibs)
include_directories(${PYTHON_INCLUDE_PATH}
./scripting)
endif(KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES)
# Automagically create version header file. # Automagically create version header file.
include(CreateBzrVersionHeader) include(CreateBzrVersionHeader)
create_bzr_version_header() create_bzr_version_header()
......
...@@ -59,6 +59,7 @@ class wxHtmlHelpController; ...@@ -59,6 +59,7 @@ class wxHtmlHelpController;
*/ */
class EDA_APP : public wxApp class EDA_APP : public wxApp
{ {
protected: protected:
/// Used mainly to handle default paths libs m_Id = APP_EESCHEMA_T, APP_PCBNEW_T ... /// Used mainly to handle default paths libs m_Id = APP_EESCHEMA_T, APP_PCBNEW_T ...
EDA_APP_T m_Id; EDA_APP_T m_Id;
...@@ -115,8 +116,8 @@ public: ...@@ -115,8 +116,8 @@ public:
* this is the first executed function (like main() ) * this is the first executed function (like main() )
* @return true if the application can be started. * @return true if the application can be started.
*/ */
bool OnInit(); bool OnInit(); // should this be virtual
wxHtmlHelpController* GetHtmlHelpController() { return m_HtmlCtrl; } wxHtmlHelpController* GetHtmlHelpController() { return m_HtmlCtrl; }
void SetHtmlHelpController( wxHtmlHelpController* aController ); void SetHtmlHelpController( wxHtmlHelpController* aController );
...@@ -408,6 +409,7 @@ public: ...@@ -408,6 +409,7 @@ public:
* @param aIndex = insertion point * @param aIndex = insertion point
*/ */
void InsertLibraryPath( const wxString& aPaths, size_t aIndex ); void InsertLibraryPath( const wxString& aPaths, size_t aIndex );
}; };
/* /*
......
...@@ -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
......
...@@ -470,7 +470,7 @@ public: ...@@ -470,7 +470,7 @@ public:
void SetShowBorderAndTitleBlock( bool aShow ) { m_showBorderAndTitleBlock = aShow; } void SetShowBorderAndTitleBlock( bool aShow ) { m_showBorderAndTitleBlock = aShow; }
EDA_DRAW_PANEL* GetCanvas() { return m_canvas; } EDA_DRAW_PANEL* GetCanvas() { return m_canvas; }
virtual wxString GetScreenDesc(); virtual wxString GetScreenDesc();
/** /**
...@@ -1072,6 +1072,19 @@ public: ...@@ -1072,6 +1072,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_
add_definitions(-DPCBNEW) add_definitions(-DPCBNEW)
if (KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES) if (KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES)
EXECUTE_PROCESS(COMMAND python2 -c "import sys;print\"%s.%s\"%sys.version_info[0:2]" OUTPUT_VARIABLE PYTHON_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
SET(PYTHON_DEST "lib/python${PYTHON_VERSION}/dist-packages" )
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripting) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripting)
FIND_PACKAGE(SWIG REQUIRED) FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE}) INCLUDE(${SWIG_USE_FILE})
FIND_PACKAGE(PythonLibs)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKICAD_SCRIPTING -DKICAD_SCRIPTING_MODULES")
endif(KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES) endif(KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES)
...@@ -25,7 +20,6 @@ include_directories( ...@@ -25,7 +20,6 @@ include_directories(
../polygon ../polygon
../common/dialogs ../common/dialogs
./scripting ./scripting
../scripting
${INC_AFTER} ${INC_AFTER}
) )
......
...@@ -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
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
*/ */
#ifdef KICAD_SCRIPTING #ifdef KICAD_SCRIPTING
#include <python_scripting.h>
#include <pcbnew_scripting_helpers.h> #include <pcbnew_scripting_helpers.h>
#endif #endif
#include <fctsys.h> #include <fctsys.h>
...@@ -51,11 +52,6 @@ ...@@ -51,11 +52,6 @@
#include <wildcards_and_files_ext.h> #include <wildcards_and_files_ext.h>
#include <class_board.h> #include <class_board.h>
#include <dialogs/dialog_scripting.h>
#ifdef KICAD_SCRIPTING
#include <python_scripting.h>
#endif
// Colors for layers and items // Colors for layers and items
COLORS_DESIGN_SETTINGS g_ColorsSettings; COLORS_DESIGN_SETTINGS g_ColorsSettings;
...@@ -87,6 +83,7 @@ wxString g_DocModulesFileName = wxT( "footprints_doc/footprints.pdf" ); ...@@ -87,6 +83,7 @@ wxString g_DocModulesFileName = wxT( "footprints_doc/footprints.pdf" );
wxArrayString g_LibraryNames; wxArrayString g_LibraryNames;
// wxWindow* DoPythonStuff(wxWindow* parent); // declaration
IMPLEMENT_APP( EDA_APP ) IMPLEMENT_APP( EDA_APP )
...@@ -105,17 +102,18 @@ void EDA_APP::MacOpenFile( const wxString& fileName ) ...@@ -105,17 +102,18 @@ void EDA_APP::MacOpenFile( const wxString& fileName )
frame->LoadOnePcbFile( fileName, false ); frame->LoadOnePcbFile( fileName, false );
} }
bool EDA_APP::OnInit() bool EDA_APP::OnInit()
{ {
wxFileName fn; wxFileName fn;
PCB_EDIT_FRAME* frame = NULL; PCB_EDIT_FRAME* frame = NULL;
#ifdef KICAD_SCRIPTING #ifdef KICAD_SCRIPTING
pcbnewInitPythonScripting(); if ( !pcbnewInitPythonScripting() )
{
return false;
}
#endif #endif
InitEDA_Appl( wxT( "Pcbnew" ), APP_PCBNEW_T ); InitEDA_Appl( wxT( "Pcbnew" ), APP_PCBNEW_T );
if( m_Checker && m_Checker->IsAnotherRunning() ) if( m_Checker && m_Checker->IsAnotherRunning() )
...@@ -212,3 +210,23 @@ Changing extension to .brd." ), GetChars( fn.GetFullPath() ) ); ...@@ -212,3 +210,23 @@ Changing extension to .brd." ), GetChars( fn.GetFullPath() ) );
return true; return true;
} }
#if 0
// for some reason KiCad classes do not implement OnExit
// if I add it in the declaration, I need to fix it in every application
// so for now make a note TODO TODO
// we need to clean up python when the application exits
int EDA_APP::OnExit() {
// Restore the thread state and tell Python to cleanup after itself.
// 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
// successful.
#if KICAD_SCRIPTING_WXPYTHON
pcbnewFinishPythonScripting();
#endif
return 0;
}
#endif
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
*/ */
#include "pcbnew_footprint_wizards.h" #include "pcbnew_footprint_wizards.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)
...@@ -27,7 +29,9 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr ...@@ -27,7 +29,9 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr
if ( pFunc && PyCallable_Check( pFunc ) ) if ( pFunc && PyCallable_Check( pFunc ) )
{ {
PyObject *result; PyObject *result;
PY_BLOCK_THREADS( blocked );
result = PyObject_CallObject( pFunc, aArglist ); result = PyObject_CallObject( pFunc, aArglist );
if ( PyErr_Occurred() ) if ( PyErr_Occurred() )
...@@ -38,6 +42,8 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr ...@@ -38,6 +42,8 @@ PyObject* PYTHON_FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aAr
printf ( "Exception: %s\n", PyString_AsString( PyObject_Str(v) ) ); printf ( "Exception: %s\n", PyString_AsString( PyObject_Str(v) ) );
printf ( " : %s\n", PyString_AsString( PyObject_Str(b) ) ); printf ( " : %s\n", PyString_AsString( PyObject_Str(b) ) );
} }
PY_UNBLOCK_THREADS( blocked );
if ( result ) if ( result )
{ {
...@@ -65,9 +71,12 @@ wxString PYTHON_FOOTPRINT_WIZARD::CallRetStrMethod( const char* aMethod, PyObjec ...@@ -65,9 +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 )
{ {
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 );
PY_UNBLOCK_THREADS( blocked );
} }
return ret; return ret;
} }
...@@ -90,6 +99,9 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod ...@@ -90,6 +99,9 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod
"result is not a list"),1 ); "result is not a list"),1 );
return ret; return ret;
} }
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++ )
...@@ -102,6 +114,8 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod ...@@ -102,6 +114,8 @@ wxArrayString PYTHON_FOOTPRINT_WIZARD::CallRetArrayStrMethod
} }
Py_DECREF( result ); Py_DECREF( result );
PY_UNBLOCK_THREADS( blocked );
} }
...@@ -137,8 +151,13 @@ int PYTHON_FOOTPRINT_WIZARD::GetNumParameterPages() ...@@ -137,8 +151,13 @@ int PYTHON_FOOTPRINT_WIZARD::GetNumParameterPages()
{ {
if ( !PyInt_Check( result ) ) if ( !PyInt_Check( result ) )
return -1; return -1;
PY_BLOCK_THREADS( blocked );
ret = PyInt_AsLong( result ); ret = PyInt_AsLong( result );
Py_DECREF( result ); Py_DECREF( result );
PY_UNBLOCK_THREADS( blocked );
} }
return ret; return ret;
} }
...@@ -156,9 +175,13 @@ wxString PYTHON_FOOTPRINT_WIZARD::GetParameterPageName( int aPage ) ...@@ -156,9 +175,13 @@ wxString PYTHON_FOOTPRINT_WIZARD::GetParameterPageName( int aPage )
if ( result ) if ( result )
{ {
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 );
PY_UNBLOCK_THREADS( blocked );
} }
return ret; return ret;
} }
...@@ -275,10 +298,12 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule() ...@@ -275,10 +298,12 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule()
if (!result) if (!result)
return NULL; return NULL;
PY_BLOCK_THREADS( blocked );
obj = PyObject_GetAttrString( result, "this" ); obj = PyObject_GetAttrString( result, "this" );
if (PyErr_Occurred()) if ( PyErr_Occurred() )
{ {
/* /*
PyObject *t, *v, *b; PyObject *t, *v, *b;
...@@ -289,8 +314,11 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule() ...@@ -289,8 +314,11 @@ MODULE *PYTHON_FOOTPRINT_WIZARD::GetModule()
*/ */
PyErr_Print(); PyErr_Print();
} }
PY_UNBLOCK_THREADS( blocked );
return PyModule_to_MODULE(obj);
MODULE *mod = PyModule_to_MODULE( obj );
return mod;
} }
...@@ -300,9 +328,10 @@ void PYTHON_FOOTPRINT_WIZARDS::register_wizard(PyObject* aPyWizard) ...@@ -300,9 +328,10 @@ void PYTHON_FOOTPRINT_WIZARDS::register_wizard(PyObject* aPyWizard)
fw = new PYTHON_FOOTPRINT_WIZARD( aPyWizard ); fw = new PYTHON_FOOTPRINT_WIZARD( aPyWizard );
printf( "Registered python footprint wizard '%s'\n",
(const char*)fw->GetName().mb_str() //printf( "Registered python footprint wizard '%s'\n",
); // (const char*)fw->GetName().mb_str()
// );
// this get the wizard registered in the common // this get the wizard registered in the common
// FOOTPRINT_WIZARDS class // FOOTPRINT_WIZARDS class
......
...@@ -30,6 +30,14 @@ ...@@ -30,6 +30,14 @@
#include <python_scripting.h> #include <python_scripting.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 */
...@@ -37,7 +45,7 @@ extern "C" void init_kicad( void ); ...@@ -37,7 +45,7 @@ extern "C" void init_kicad( void );
extern "C" void init_pcbnew( void ); extern "C" void init_pcbnew( void );
#define EXTRA_PYTHON_MODULES 2 // this is the number of python #define EXTRA_PYTHON_MODULES 10 // this is the number of python
// modules that we want to add into the list // modules that we want to add into the list
...@@ -112,21 +120,175 @@ static void swigSwitchPythonBuiltin() ...@@ -112,21 +120,175 @@ static void swigSwitchPythonBuiltin()
/* Function pcbnewInitPythonScripting /* Function pcbnewInitPythonScripting
* Initializes all the python environment and publish our interface inside it * Initializes all the python environment and publish our interface inside it
* initializes all the wxpython interface, and returns the python thread control structure
* *
*/ */
void pcbnewInitPythonScripting()
PyThreadState *g_PythonMainTState;
bool pcbnewInitPythonScripting()
{ {
swigAddBuiltin(); // add builtin functions swigAddBuiltin(); // add builtin functions
swigAddModules(); // add our own modules swigAddModules(); // add our own modules
swigSwitchPythonBuiltin(); // switch the python builtin modules to our new list swigSwitchPythonBuiltin(); // switch the python builtin modules to our new list
Py_Initialize(); // call the python library to get it initialized Py_Initialize();
#ifdef KICAD_SCRIPTING_WXPYTHON
PyEval_InitThreads();
// Load the wxPython core API. Imports the wx._core_ module and sets a
// local pointer to a function table located there. The pointer is used
// internally by the rest of the API functions.
if ( ! wxPyCoreAPI_IMPORT() ) {
wxLogError(wxT("***** Error importing the wxPython API! *****"));
PyErr_Print();
Py_Finalize();
return false;
}
// Save the current Python thread state and release the
// Global Interpreter Lock.
g_PythonMainTState = wxPyBeginAllowThreads();
// 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
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()"
); );
PY_UNBLOCK_THREADS( blocked );
return true;
}
void pcbnewFinishPythonScripting()
{
#ifdef KICAD_SCRIPTING_WXPYTHON
wxPyEndAllowThreads(g_PythonMainTState);
#endif
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
#ifndef __PYTHON_SCRIPTING_H #ifndef __PYTHON_SCRIPTING_H
#define __PYTHON_SCRIPTING_H #define __PYTHON_SCRIPTING_H
#include <Python.h> // undefs explained here: https://bugzilla.redhat.com/show_bug.cgi?id=427617
#ifdef _POSIX_C_SOURCE
#undef _POSIX_C_SOURCE
#endif
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
#endif
#include <Python.h>
#ifndef NO_WXPYTHON_EXTENSION_HEADERS
#ifdef KICAD_SCRIPTING_WXPYTHON
#include <wx/wxPython/wxPython.h>
#endif
#endif
/* Function pcbnewInitPythonScripting /* Function pcbnewInitPythonScripting
* Initializes the Python engine inside pcbnew * Initializes the Python engine inside pcbnew
*/ */
void pcbnewInitPythonScripting( void ); bool pcbnewInitPythonScripting();
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