Centralizing SCRIPTING class

This commit is contained in:
Seth Hillbrand 2021-03-18 06:28:04 -07:00
parent 192fbfd5e5
commit c7d188a8d0
26 changed files with 171 additions and 538 deletions

View File

@ -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

View File

@ -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();

View File

@ -404,6 +404,7 @@ target_link_libraries( eeschema_kiface
common
sexpr
markdown_lib
scripting
${wxWidgets_LIBRARIES}
${GDI_PLUS_LIBRARIES}
)

View File

@ -29,6 +29,7 @@
#include <kiface_i.h>
#include <bitmaps.h>
#include <eeschema_id.h>
#include <python_scripting.h>
#include <tool/tool_manager.h>
#include <tool/action_toolbar.h>
#include <tools/ee_actions.h>
@ -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();
}

View File

@ -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
//

View File

@ -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;

View File

@ -36,6 +36,7 @@
#include <invoke_sch_dialog.h>
#include <kicad_string.h>
#include <kiway.h>
#include <kiway_player.h>
#include <netlist_exporters/netlist_exporter_pspice.h>
#include <project/project_file.h>
#include <project/net_settings.h>
@ -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() );
}

View File

@ -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 );

View File

@ -90,6 +90,11 @@ public:
*/
void ReleaseFile();
/**
* Toggles the scripting console visibility
*/
void ScriptingConsoleEnableDisable();
wxFindReplaceData& GetFindReplaceData() { return *m_findReplaceData; }
wxArrayString& GetFindHistoryList() { return m_findStringHistoryList; }

View File

@ -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

View File

@ -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();

View File

@ -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}
)

View File

@ -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 <miguelangel@nbee.es>
* 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 <Python.h>
#undef HAVE_CLOCK_GETTIME // macro is defined in Python.h and causes redefine warning
#include <pcb_edit_frame.h>
#include <dialog_scripting.h>
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 );
}

View File

@ -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 <miguelangel@nbee.es>
* 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 <dialog_scripting_base.h>
class DIALOG_SCRIPTING: public DIALOG_SCRIPTING_BASE
{
public:
DIALOG_SCRIPTING( wxWindow * parent );
private:
void OnRunButtonClick( wxCommandEvent& event ) override;
};
#endif // _DIALOG_SCRIPTING_H_

View File

@ -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 );
}

View File

@ -1,202 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<wxFormBuilder_Project>
<FileVersion major="1" minor="15" />
<object class="Project" expanded="1">
<property name="class_decoration"></property>
<property name="code_generation">C++</property>
<property name="disconnect_events">1</property>
<property name="disconnect_mode">source_name</property>
<property name="disconnect_php_events">0</property>
<property name="disconnect_python_events">0</property>
<property name="embedded_files_path">res</property>
<property name="encoding">UTF-8</property>
<property name="event_generation">connect</property>
<property name="file">dialog_scripting_base</property>
<property name="first_id">1000</property>
<property name="help_provider">none</property>
<property name="indent_with_spaces"></property>
<property name="internationalize">1</property>
<property name="name">DIALOG_SCRIPTING_BASE</property>
<property name="namespace"></property>
<property name="path">.</property>
<property name="precompiled_header"></property>
<property name="relative_path">1</property>
<property name="skip_lua_events">1</property>
<property name="skip_php_events">1</property>
<property name="skip_python_events">1</property>
<property name="ui_table">UI</property>
<property name="use_enum">0</property>
<property name="use_microsoft_bom">0</property>
<object class="Frame" expanded="1">
<property name="aui_managed">0</property>
<property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
<property name="bg"></property>
<property name="center">wxBOTH</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="enabled">1</property>
<property name="event_handler">impl_virtual</property>
<property name="extra_style"></property>
<property name="fg"></property>
<property name="font"></property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size"></property>
<property name="name">DIALOG_SCRIPTING_BASE</property>
<property name="pos"></property>
<property name="size">-1,-1</property>
<property name="style">wxDEFAULT_FRAME_STYLE</property>
<property name="subclass"></property>
<property name="title">Scripting Test Window</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<property name="xrc_skip_sizer">1</property>
<object class="wxBoxSizer" expanded="1">
<property name="minimum_size"></property>
<property name="name">bSizerMain</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxTextCtrl" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size">480,500</property>
<property name="moveable">1</property>
<property name="name">m_txScript</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxHSCROLL|wxTE_MULTILINE</property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">5</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxButton" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">&amp;Run</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_btRun</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnButtonClick">OnRunButtonClick</event>
</object>
</object>
</object>
</object>
</object>
</wxFormBuilder_Project>

View File

@ -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 <wx/artprov.h>
#include <wx/xrc/xmlres.h>
#include <wx/intl.h>
#include <wx/string.h>
#include <wx/textctrl.h>
#include <wx/gdicmn.h>
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/bitmap.h>
#include <wx/image.h>
#include <wx/icon.h>
#include <wx/button.h>
#include <wx/sizer.h>
#include <wx/frame.h>
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
/// 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();
};

View File

@ -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).

View File

@ -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.

View File

@ -60,6 +60,10 @@
#include <wildcards_and_files_ext.h>
/* 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<void*>( PyInit__pcbnew );
default:
return nullptr;
}

View File

@ -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<void>( wxTheApp );
s_SettingsManager = new SETTINGS_MANAGER( true );
}

View File

@ -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 );

View File

@ -88,6 +88,7 @@ add_dependencies( qa_eeschema eeschema )
target_link_libraries( qa_eeschema
common
pcbcommon
scripting
kimath
qa_utils
markdown_lib

View File

@ -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 );
}

View File

@ -40,6 +40,8 @@
#include <kicad_string.h>
#include <macros.h>
#include <kiface_ids.h>
#include <kiway.h>
#include <paths.h>
#include <pgm_base.h>
#include <settings/settings_manager.h>
@ -50,26 +52,82 @@
#include <config.h>
/* 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<initfunc>( 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;

View File

@ -45,6 +45,28 @@
#include <wx/string.h>
#include <wx/arrstr.h>
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();