diff --git a/common/eda_draw_frame.cpp b/common/eda_draw_frame.cpp index 5e3fe11d6a..67e2ee07b4 100644 --- a/common/eda_draw_frame.cpp +++ b/common/eda_draw_frame.cpp @@ -199,6 +199,35 @@ bool EDA_DRAW_FRAME::LockFile( const wxString& aFileName ) } +void EDA_DRAW_FRAME::ScriptingConsoleEnableDisable() +{ + KIWAY_PLAYER* frame = Kiway().Player( FRAME_PYTHON, false ); + + if( !frame ) + { + frame = Kiway().Player( FRAME_PYTHON, true, Kiway().GetTop() ); + + // If we received an error in the CTOR due to Python-ness, don't crash + if( !frame ) + return; + + if( !frame->IsVisible() ) + frame->Show( true ); + + // On Windows, Raise() does not bring the window on screen, when iconized + if( frame->IsIconized() ) + frame->Iconize( false ); + + frame->Raise(); + + return; + } + + frame->Show( !frame->IsVisible() ); + +} + + void EDA_DRAW_FRAME::unitsChangeRefresh() { // Notify all tools the units have changed diff --git a/common/pgm_base.cpp b/common/pgm_base.cpp index 9b789946ed..eccf6ef277 100644 --- a/common/pgm_base.cpp +++ b/common/pgm_base.cpp @@ -204,6 +204,7 @@ const wxString PGM_BASE::AskUserForPreferredEditor( const wxString& aDefaultEdit bool PGM_BASE::InitPgm( bool aHeadless ) { + printf("InitPgm()\n"); wxFileName pgm_name( App().argv[0] ); wxInitAllImageHandlers(); diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index 1684c35a84..1bcfddc402 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -404,6 +404,7 @@ target_link_libraries( eeschema_kiface common sexpr markdown_lib + scripting ${wxWidgets_LIBRARIES} ${GDI_PLUS_LIBRARIES} ) diff --git a/eeschema/toolbars_sch_editor.cpp b/eeschema/toolbars_sch_editor.cpp index 504857fd9e..32fbaf2094 100644 --- a/eeschema/toolbars_sch_editor.cpp +++ b/eeschema/toolbars_sch_editor.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -111,6 +112,13 @@ void SCH_EDIT_FRAME::ReCreateHToolbar() m_mainToolBar->AddScaledSeparator( this ); m_mainToolBar->Add( EE_ACTIONS::showPcbNew ); + // Access to the scripting console + if( SCRIPTING::IsWxAvailable() ) + { + m_mainToolBar->AddScaledSeparator( this ); + m_mainToolBar->Add( EE_ACTIONS::showPythonConsole, ACTION_TOOLBAR::TOGGLE ); + } + // after adding the tools to the toolbar, must call Realize() to reflect the changes m_mainToolBar->KiRealize(); } diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp index d462f21278..cc8ac15aa2 100644 --- a/eeschema/tools/ee_actions.cpp +++ b/eeschema/tools/ee_actions.cpp @@ -643,6 +643,11 @@ TOOL_ACTION EE_ACTIONS::toggleForceHV( "eeschema.EditorControl.forceHVLines", _( "Force H/V Wires and Buses" ), _( "Switch H & V only mode for new wires and buses" ), BITMAPS::lines90 ); +// Python Console +TOOL_ACTION EE_ACTIONS::showPythonConsole( "eeschema.EditorControl.showPythonConsole", + AS_GLOBAL, 0, "", + _( "Scripting Console" ), _( "Show the Python scripting console" ), + BITMAPS::py_script ); // SCH_NAVIGATE_TOOL // diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h index e15c2f17ad..2c30556bf6 100644 --- a/eeschema/tools/ee_actions.h +++ b/eeschema/tools/ee_actions.h @@ -204,6 +204,7 @@ public: static TOOL_ACTION drawSheetOnClipboard; static TOOL_ACTION exportSymbolView; static TOOL_ACTION exportSymbolAsSVG; + static TOOL_ACTION showPythonConsole; // SPICE static TOOL_ACTION runSimulation; diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp index f8caf1176c..55d226a440 100644 --- a/eeschema/tools/sch_editor_control.cpp +++ b/eeschema/tools/sch_editor_control.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -1959,6 +1960,14 @@ int SCH_EDITOR_CONTROL::ToggleForceHV( const TOOL_EVENT& aEvent ) } +int SCH_EDITOR_CONTROL::TogglePythonConsole( const TOOL_EVENT& aEvent ) +{ + + m_frame->ScriptingConsoleEnableDisable(); + return 0; +} + + void SCH_EDITOR_CONTROL::setTransitions() { Go( &SCH_EDITOR_CONTROL::New, ACTIONS::doNew.MakeEvent() ); @@ -2032,4 +2041,6 @@ void SCH_EDITOR_CONTROL::setTransitions() Go( &SCH_EDITOR_CONTROL::ToggleHiddenPins, EE_ACTIONS::toggleHiddenPins.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::ToggleHiddenFields, EE_ACTIONS::toggleHiddenFields.MakeEvent() ); Go( &SCH_EDITOR_CONTROL::ToggleForceHV, EE_ACTIONS::toggleForceHV.MakeEvent() ); + + Go( &SCH_EDITOR_CONTROL::TogglePythonConsole, EE_ACTIONS::showPythonConsole.MakeEvent() ); } diff --git a/eeschema/tools/sch_editor_control.h b/eeschema/tools/sch_editor_control.h index 6a620851ab..fa02505b97 100644 --- a/eeschema/tools/sch_editor_control.h +++ b/eeschema/tools/sch_editor_control.h @@ -135,6 +135,7 @@ public: int ToggleHiddenPins( const TOOL_EVENT& aEvent ); int ToggleHiddenFields( const TOOL_EVENT& aEvent ); int ToggleForceHV( const TOOL_EVENT& aEvent ); + int TogglePythonConsole( const TOOL_EVENT& aEvent ); void AssignFootprints( const std::string& aChangedSetOfReferences ); diff --git a/include/eda_draw_frame.h b/include/eda_draw_frame.h index 4bdbe0c18f..27a9af133e 100644 --- a/include/eda_draw_frame.h +++ b/include/eda_draw_frame.h @@ -90,6 +90,11 @@ public: */ void ReleaseFile(); + /** + * Toggles the scripting console visibility + */ + void ScriptingConsoleEnableDisable(); + wxFindReplaceData& GetFindReplaceData() { return *m_findReplaceData; } wxArrayString& GetFindHistoryList() { return m_findStringHistoryList; } diff --git a/include/kiface_ids.h b/include/kiface_ids.h index 04efb864d9..7b2b3de0b3 100644 --- a/include/kiface_ids.h +++ b/include/kiface_ids.h @@ -1,7 +1,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2017 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2017-2021 KiCad Developers, see AUTHORS.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 @@ -56,7 +56,8 @@ enum KIFACE_ADDR_ID : int KIFACE_LOAD_PCB, KIFACE_LOAD_SCHEMATIC, KIFACE_NETLIST_SCHEMATIC, - KIFACE_SCRIPTING_WINDOW + KIFACE_SCRIPTING_LEGACY, + KIFACE_SCRIPTING }; #endif // KIFACE_IDS diff --git a/include/kiway.h b/include/kiway.h index f74f21aa3e..91d3c06110 100644 --- a/include/kiway.h +++ b/include/kiway.h @@ -383,6 +383,7 @@ public: * @param aTop is the top most wxFrame in the entire program. */ void SetTop( wxFrame* aTop ); + wxFrame* GetTop() { return m_top; } void OnKiCadExit(); diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 7d6b4945fb..249bdb7b16 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -364,11 +364,6 @@ set( PCBNEW_COMMON_SRCS ${CMAKE_SOURCE_DIR}/common/base_units.cpp ) -set( PCBNEW_SCRIPTING_DIALOGS - dialogs/dialog_scripting.cpp - dialogs/dialog_scripting_base.cpp - ) - set( PCBNEW_SCRIPTING_PYTHON_HELPERS ${CMAKE_SOURCE_DIR}/common/swig/wx_python_helpers.cpp swig/pcbnew_action_plugins.cpp @@ -382,7 +377,7 @@ if( COMPILER_SUPPORTS_WARNINGS ) # Only compile our source files with the warnings, since the SWIG generated # files contain a lot of warnings, we just ignore it. set_source_files_properties( - ${PCBNEW_SRCS} ${PCBNEW_COMMON_SRCS} ${PCBNEW_SCRIPTING_DIALOGS} ${PCBNEW_SCRIPTING_PYTHON_HELPERS} + ${PCBNEW_SRCS} ${PCBNEW_COMMON_SRCS} ${PCBNEW_SCRIPTING_PYTHON_HELPERS} PROPERTIES COMPILE_FLAGS ${WARN_FLAGS_CXX} ) endif() @@ -400,7 +395,6 @@ if( CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) endif() set( PCBNEW_SCRIPTING_SRCS - ${PCBNEW_SCRIPTING_DIALOGS} pcbnew_wrap.cxx ${PCBNEW_SCRIPTING_PYTHON_HELPERS} ) diff --git a/pcbnew/dialogs/dialog_scripting.cpp b/pcbnew/dialogs/dialog_scripting.cpp deleted file mode 100644 index f3e3dcdac7..0000000000 --- a/pcbnew/dialogs/dialog_scripting.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2012-2014 Miguel Angel Ajo - * Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.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 2 - * 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/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/** - * @file dialog_scripting.cpp - */ - - -#include -#undef HAVE_CLOCK_GETTIME // macro is defined in Python.h and causes redefine warning - -#include -#include - - -DIALOG_SCRIPTING::DIALOG_SCRIPTING( wxWindow* parent ) - : DIALOG_SCRIPTING_BASE( parent ) -{ - SetFocus(); - -} - - - -void DIALOG_SCRIPTING::OnRunButtonClick( wxCommandEvent& event ) -{ - wxCharBuffer buffer = m_txScript->GetValue().ToUTF8(); - int retv = PyRun_SimpleString( buffer.data()) ; - - if( retv != 0 ) - wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, buffer ); -} diff --git a/pcbnew/dialogs/dialog_scripting.h b/pcbnew/dialogs/dialog_scripting.h deleted file mode 100644 index a3271d7872..0000000000 --- a/pcbnew/dialogs/dialog_scripting.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2012-2014 Miguel Angel Ajo - * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.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 2 - * 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/old-licenses/gpl-2.0.html - * or you may search the http://www.gnu.org website for the version 2 license, - * or you may write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef _DIALOG_SCRIPTING_H_ -#define _DIALOG_SCRIPTING_H_ - -#include - -class DIALOG_SCRIPTING: public DIALOG_SCRIPTING_BASE -{ -public: - DIALOG_SCRIPTING( wxWindow * parent ); - -private: - void OnRunButtonClick( wxCommandEvent& event ) override; -}; - -#endif // _DIALOG_SCRIPTING_H_ diff --git a/pcbnew/dialogs/dialog_scripting_base.cpp b/pcbnew/dialogs/dialog_scripting_base.cpp deleted file mode 100644 index 24afc9b20d..0000000000 --- a/pcbnew/dialogs/dialog_scripting_base.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Nov 23 2018) -// http://www.wxformbuilder.org/ -// -// PLEASE DO *NOT* EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#include "dialog_scripting_base.h" - -/////////////////////////////////////////////////////////////////////////// - -DIALOG_SCRIPTING_BASE::DIALOG_SCRIPTING_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizerMain; - bSizerMain = new wxBoxSizer( wxVERTICAL ); - - m_txScript = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxHSCROLL|wxTE_MULTILINE ); - m_txScript->SetMinSize( wxSize( 480,500 ) ); - - bSizerMain->Add( m_txScript, 1, wxALL|wxEXPAND, 5 ); - - m_btRun = new wxButton( this, wxID_ANY, _("&Run"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerMain->Add( m_btRun, 0, wxALL, 5 ); - - - this->SetSizer( bSizerMain ); - this->Layout(); - bSizerMain->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - m_btRun->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCRIPTING_BASE::OnRunButtonClick ), NULL, this ); -} - -DIALOG_SCRIPTING_BASE::~DIALOG_SCRIPTING_BASE() -{ - // Disconnect Events - m_btRun->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_SCRIPTING_BASE::OnRunButtonClick ), NULL, this ); - -} diff --git a/pcbnew/dialogs/dialog_scripting_base.fbp b/pcbnew/dialogs/dialog_scripting_base.fbp deleted file mode 100644 index 55be1eafa8..0000000000 --- a/pcbnew/dialogs/dialog_scripting_base.fbp +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - C++ - 1 - source_name - 0 - 0 - res - UTF-8 - connect - dialog_scripting_base - 1000 - none - - 1 - DIALOG_SCRIPTING_BASE - - . - - 1 - 1 - 1 - 1 - UI - 0 - 0 - - 0 - wxAUI_MGR_DEFAULT - - wxBOTH - - 1 - 1 - impl_virtual - - - - 0 - wxID_ANY - - - DIALOG_SCRIPTING_BASE - - -1,-1 - wxDEFAULT_FRAME_STYLE - - Scripting Test Window - - - - wxTAB_TRAVERSAL - 1 - - - bSizerMain - wxVERTICAL - none - - 5 - wxALL|wxEXPAND - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - 480,500 - 1 - m_txScript - 1 - - - protected - 1 - - Resizable - 1 - - wxHSCROLL|wxTE_MULTILINE - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - - 1 - 0 - 1 - - 1 - - 0 - 0 - - Dock - 0 - Left - 1 - - 1 - - - 0 - 0 - wxID_ANY - &Run - - 0 - - 0 - - - 0 - - 1 - m_btRun - 1 - - - protected - 1 - - - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnRunButtonClick - - - - - - diff --git a/pcbnew/dialogs/dialog_scripting_base.h b/pcbnew/dialogs/dialog_scripting_base.h deleted file mode 100644 index 9c679451ad..0000000000 --- a/pcbnew/dialogs/dialog_scripting_base.h +++ /dev/null @@ -1,51 +0,0 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Nov 23 2018) -// http://www.wxformbuilder.org/ -// -// PLEASE DO *NOT* EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -/// Class DIALOG_SCRIPTING_BASE -/////////////////////////////////////////////////////////////////////////////// -class DIALOG_SCRIPTING_BASE : public wxFrame -{ - private: - - protected: - wxTextCtrl* m_txScript; - wxButton* m_btRun; - - // Virtual event handlers, overide them in your derived class - virtual void OnRunButtonClick( wxCommandEvent& event ) { event.Skip(); } - - - public: - - DIALOG_SCRIPTING_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Scripting Test Window"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL ); - - ~DIALOG_SCRIPTING_BASE(); - -}; - diff --git a/pcbnew/pcb_edit_frame.cpp b/pcbnew/pcb_edit_frame.cpp index 2166e33e21..4fbe479064 100644 --- a/pcbnew/pcb_edit_frame.cpp +++ b/pcbnew/pcb_edit_frame.cpp @@ -550,7 +550,7 @@ void PCB_EDIT_FRAME::setupUIConditions() auto pythonConsoleCond = [] ( const SELECTION& ) { - if( IsWxPythonLoaded() ) + if( SCRIPTING::IsWxAvailable() ) { wxWindow* console = PCB_EDIT_FRAME::findPythonConsole(); return console && console->IsShown(); @@ -1291,35 +1291,6 @@ void PCB_EDIT_FRAME::UpdateUserInterface() } -void PCB_EDIT_FRAME::ScriptingConsoleEnableDisable() -{ - KIWAY_PLAYER* frame = Kiway().Player( FRAME_PYTHON, false ); - - if( !frame ) - { - 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 ); - - // On Windows, Raise() does not bring the window on screen, when iconized - if( frame->IsIconized() ) - frame->Iconize( false ); - - frame->Raise(); - - return; - } - - frame->Show( !frame->IsVisible() ); - -} - - void PCB_EDIT_FRAME::SwitchCanvas( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) { // switches currently used canvas (Cairo / OpenGL). diff --git a/pcbnew/pcb_edit_frame.h b/pcbnew/pcb_edit_frame.h index 3fd99f8811..94659c72b2 100644 --- a/pcbnew/pcb_edit_frame.h +++ b/pcbnew/pcb_edit_frame.h @@ -605,11 +605,6 @@ public: */ void OnNetlistChanged( BOARD_NETLIST_UPDATER& aUpdater, bool* aRunDragCommand ); - /** - * Enable or disable the scripting console. - */ - void ScriptingConsoleEnableDisable(); - /** * Send a message to the schematic editor so that it may move its cursor * to a symbol with the same reference as the \a objectToSync. diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index 3a9dc31bbd..a3a78598c6 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -60,6 +60,10 @@ #include +/* init functions defined by swig */ + +extern "C" PyObject* PyInit__pcbnew( void ); + namespace PCB { static struct IFACE : public KIFACE_I @@ -159,6 +163,9 @@ static struct IFACE : public KIFACE_I case KIFACE_GLOBAL_FOOTPRINT_TABLE: return (void*) &GFootprintTable; + case KIFACE_SCRIPTING_LEGACY: + return reinterpret_cast( PyInit__pcbnew ); + default: return nullptr; } diff --git a/pcbnew/swig/pcbnew_scripting_helpers.cpp b/pcbnew/swig/pcbnew_scripting_helpers.cpp index 77052059f8..2aab89f0e6 100644 --- a/pcbnew/swig/pcbnew_scripting_helpers.cpp +++ b/pcbnew/swig/pcbnew_scripting_helpers.cpp @@ -53,18 +53,6 @@ static PCB_EDIT_FRAME* s_PcbEditFrame = NULL; static SETTINGS_MANAGER* s_SettingsManager = nullptr; -/// A valid app is needed for preventing some asserts when opening the settings manager -static wxApp* s_WxApp = nullptr; - - -wxApp* GetApp() -{ - if( !s_WxApp ) - s_WxApp = new wxApp(); - - return s_WxApp; -} - BOARD* GetBoard() { @@ -98,7 +86,7 @@ SETTINGS_MANAGER* GetSettingsManager() if( !s_SettingsManager ) { // Ensure wx system settings stuff is available - GetApp(); + static_cast( wxTheApp ); s_SettingsManager = new SETTINGS_MANAGER( true ); } diff --git a/pcbnew/toolbars_pcb_editor.cpp b/pcbnew/toolbars_pcb_editor.cpp index f23632b10b..f12d9a28d6 100644 --- a/pcbnew/toolbars_pcb_editor.cpp +++ b/pcbnew/toolbars_pcb_editor.cpp @@ -294,7 +294,7 @@ void PCB_EDIT_FRAME::ReCreateHToolbar() m_mainToolBar->Add( PCB_ACTIONS::showEeschema ); // Access to the scripting console - if( IsWxPythonLoaded() ) + if( SCRIPTING::IsWxAvailable() ) { m_mainToolBar->AddScaledSeparator( this ); m_mainToolBar->Add( PCB_ACTIONS::showPythonConsole, ACTION_TOOLBAR::TOGGLE ); diff --git a/qa/eeschema/CMakeLists.txt b/qa/eeschema/CMakeLists.txt index 69ddc9997f..254e6fbce2 100644 --- a/qa/eeschema/CMakeLists.txt +++ b/qa/eeschema/CMakeLists.txt @@ -88,6 +88,7 @@ add_dependencies( qa_eeschema eeschema ) target_link_libraries( qa_eeschema common pcbcommon + scripting kimath qa_utils markdown_lib diff --git a/scripting/kicad_scripting_main.cpp b/scripting/kicad_scripting_main.cpp index d37af5a65e..486ea56283 100644 --- a/scripting/kicad_scripting_main.cpp +++ b/scripting/kicad_scripting_main.cpp @@ -114,7 +114,6 @@ bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) InitSettings( new KIPYTHON_SETTINGS ); Pgm().GetSettingsManager().RegisterSettings( KifaceSettings() ); - ScriptingSetup(); return start_common( aCtlBits ); } diff --git a/scripting/python_scripting.cpp b/scripting/python_scripting.cpp index 1cda0a60ea..cf13753953 100644 --- a/scripting/python_scripting.cpp +++ b/scripting/python_scripting.cpp @@ -40,6 +40,8 @@ #include #include +#include +#include #include #include #include @@ -50,26 +52,82 @@ #include -/* init functions defined by swig */ - -extern "C" PyObject* PyInit__pcbnew( void ); +using initfunc = PyObject* (*)(void); -/// True if the wxPython scripting layer was successfully loaded. -static bool wxPythonLoaded = false; - - -bool IsWxPythonLoaded() +SCRIPTING::SCRIPTING( KIWAY* aKiway ) { - return wxPythonLoaded; + int retv; + char cmd[1024]; + + scriptingSetup(); + + KIFACE* pcbnew_kiface = nullptr; + + pcbnew_kiface = aKiway->KiFACE( KIWAY::FACE_PCB ); + initfunc pcbnew_init = reinterpret_cast( pcbnew_kiface->IfaceOrAddress( KIFACE_SCRIPTING_LEGACY ) ); + PyImport_AppendInittab( "_pcbnew", pcbnew_init ); + +#ifdef _MSC_VER + // Under vcpkg/msvc, we need to explicitly set the python home + // or else it'll start consuming system python registry keys and the like instead + // We are going to follow the "unix" layout for the msvc/vcpkg distributions so exes in /root/bin + // And the python lib in /root/lib/python3(/Lib,/DLLs) + wxFileName pyHome; + + pyHome.Assign( Pgm().GetExecutablePath() ); + + pyHome.Normalize(); + + // MUST be called before Py_Initialize so it will to create valid default lib paths + if( !wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) ) + { + Py_SetPythonHome( pyHome.GetFullPath().c_str() ); + } +#endif +// +// Py_Initialize(); + pybind11::initialize_interpreter(); + +// PySys_SetArgv( Pgm().App().argc, Pgm().App().argv ); + +#if PY_VERSION_HEX < 0x03070000 // PyEval_InitThreads() is called by Py_Initialize() starting with version 3.7 + PyEval_InitThreads(); +#endif // if PY_VERSION_HEX < 0x03070000 + + // Save the current Python thread state and release the + // Global Interpreter Lock. + m_python_thread_state = PyEval_SaveThread(); + + // Load pcbnew inside Python and load all the user plugins and package-based plugins + { + PyLOCK lock; + + // Load os so that we can modify the environment variables through python + snprintf( cmd, sizeof( cmd ), "import sys, os, traceback\n" + "sys.path.append(\".\")\n" + "import pcbnew\n" + "pcbnew.LoadPlugins(\"%s\", \"%s\")", + TO_UTF8( PyScriptingPath() ), TO_UTF8( PyScriptingPath( true) ) ); + retv = PyRun_SimpleString( cmd ); + + if( retv != 0 ) + wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, cmd ); + } } -PyThreadState* g_PythonMainTState; +SCRIPTING::~SCRIPTING() +{ + PyEval_RestoreThread( m_python_thread_state ); + pybind11::finalize_interpreter(); +} +bool SCRIPTING::IsWxAvailable() +{ + return true; +} - - -bool ScriptingSetup() +bool SCRIPTING::scriptingSetup() { #if defined( __WINDOWS__ ) // If our python.exe (in kicad/bin) exists, force our kicad python environment @@ -151,76 +209,6 @@ bool ScriptingSetup() if( !path.DirExists() && !path.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) ) wxLogError( "Warning: could not create user scripting path %s", path.GetPath() ); - if( !InitPythonScripting( TO_UTF8( PyScriptingPath() ), TO_UTF8( PyScriptingPath( true ) ) ) ) - { - wxLogError( "InitPythonScripting() failed." ); - return false; - } - - return true; -} - -/** - * Initialize the python environment and publish the Pcbnew interface inside it. - * - * This initializes all the wxPython interface and returns the python thread control structure - */ -bool InitPythonScripting( const char* aStockScriptingPath, const char* aUserScriptingPath ) -{ - int retv; - char cmd[1024]; - - PyImport_AppendInittab( "_pcbnew", PyInit__pcbnew ); - -#ifdef _MSC_VER - // Under vcpkg/msvc, we need to explicitly set the python home - // or else it'll start consuming system python registry keys and the like instead - // We are going to follow the "unix" layout for the msvc/vcpkg distributions so exes in /root/bin - // And the python lib in /root/lib/python3(/Lib,/DLLs) - wxFileName pyHome; - - pyHome.Assign( Pgm().GetExecutablePath() ); - - pyHome.Normalize(); - - // MUST be called before Py_Initialize so it will to create valid default lib paths - if( !wxGetEnv( wxT( "KICAD_RUN_FROM_BUILD_DIR" ), nullptr ) ) - { - Py_SetPythonHome( pyHome.GetFullPath().c_str() ); - } -#endif -// -// Py_Initialize(); - pybind11::initialize_interpreter(); - -// PySys_SetArgv( Pgm().App().argc, Pgm().App().argv ); - -#if PY_VERSION_HEX < 0x03070000 // PyEval_InitThreads() is called by Py_Initialize() starting with version 3.7 - PyEval_InitThreads(); -#endif // if PY_VERSION_HEX < 0x03070000 - - wxPythonLoaded = true; - - // Save the current Python thread state and release the - // Global Interpreter Lock. - g_PythonMainTState = PyEval_SaveThread(); - - // Load pcbnew inside Python and load all the user plugins and package-based plugins - { - PyLOCK lock; - - // Load os so that we can modify the environment variables through python - snprintf( cmd, sizeof( cmd ), "import sys, os, traceback\n" - "sys.path.append(\".\")\n" - "import pcbnew\n" - "pcbnew.LoadPlugins(\"%s\", \"%s\")", - aStockScriptingPath, aUserScriptingPath ); - retv = PyRun_SimpleString( cmd ); - - if( retv != 0 ) - wxLogError( "Python error %d occurred running command:\n\n`%s`", retv, cmd ); - } - return true; } @@ -292,13 +280,6 @@ static void RunPythonMethodWithReturnedString( const char* aMethodName, wxString } -void FinishPythonScripting() -{ - PyEval_RestoreThread( g_PythonMainTState ); - pybind11::finalize_interpreter(); -} - - wxString PyEscapeString( const wxString& aSource ) { wxString converted; diff --git a/scripting/python_scripting.h b/scripting/python_scripting.h index f116b57e9e..56a25ca1e0 100644 --- a/scripting/python_scripting.h +++ b/scripting/python_scripting.h @@ -45,6 +45,28 @@ #include #include +class KIWAY; + +class SCRIPTING +{ +public: + SCRIPTING( KIWAY* aKiway ); + ~SCRIPTING(); + + /// We do not allow secondary creation of the scripting system + SCRIPTING( SCRIPTING const& ) = delete; + void operator= ( SCRIPTING const& ) = delete; + + static bool IsWxAvailable(); + +private: + + bool scriptingSetup(); + + PyThreadState* m_python_thread_state; + + KIWAY* aKiway; +}; /** * Set an environment variable in the current Python interpreter. @@ -56,7 +78,6 @@ void UpdatePythonEnvVar( const wxString& aVar, const wxString& aValue ); void RedirectStdio(); wxWindow* CreatePythonShellWindow( wxWindow* parent, const wxString& aFramenameId ); -bool ScriptingSetup(); bool InitPythonScripting( const char* aStockScriptingPath, const char* aUserScriptingPath ); bool IsWxPythonLoaded();