KiCad PCB EDA Suite
pcb_scripting_tool.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2021 KiCad Developers, see CHANGELOG.TXT for contributors.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 3
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/gpl-3.0.html
19  * or you may search the http://www.gnu.org website for the version 3 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include "pcb_scripting_tool.h"
25 
26 #include <action_plugin.h>
27 #include <gestfich.h>
28 #include <kiface_ids.h>
29 #include <kiway.h>
30 #include <macros.h>
31 #include <python_scripting.h>
32 #include <tools/pcb_actions.h>
33 
34 #include <pybind11/eval.h>
35 
36 #include <Python.h>
37 #include <wx/string.h>
38 #include <launch_ext.h>
39 
40 using initfunc = PyObject* (*)(void);
41 
43  PCB_TOOL_BASE( "pcbnew.ScriptingTool" )
44 {}
45 
46 
48 {}
49 
50 
52 {
53 }
54 
55 
57 {
58  PyLOCK lock;
59  std::string pymodule( "_pcbnew" );
60 
61  if( !SCRIPTING::IsModuleLoaded( pymodule ) )
62  {
64  initfunc pcbnew_init = reinterpret_cast<initfunc>( kiface->IfaceOrAddress( KIFACE_SCRIPTING_LEGACY ) );
65  PyImport_AddModule( pymodule.c_str() );
66  PyObject* mod = pcbnew_init();
67  PyObject* sys_mod = PyImport_GetModuleDict();
68  PyDict_SetItemString( sys_mod, "_pcbnew", mod );
69  Py_DECREF( mod );
70  }
71 
72  // Load pcbnew inside Python and load all the user plugins and package-based plugins
73  {
74  using namespace pybind11::literals;
75 
76  auto locals = pybind11::dict( "sys_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( false ) ),
77  "user_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( true ) ) );
78 
79  pybind11::exec( R"(
80 import sys
81 import pcbnew
82 pcbnew.LoadPlugins( sys_path, user_path )
83  )", pybind11::globals(), locals );
84 
85  }
86 
87  return true;
88 }
89 
90 
92 {
93  if( !m_isFootprintEditor )
94  // Reload Python plugins if they are newer than the already loaded, and load new plugins
95  // Remove all action plugins so that we don't keep references to old versions
97 
98  {
99  PyLOCK lock;
100  std::string sys_path = SCRIPTING::PyScriptingPath( false ).ToStdString();
101  std::string user_path = SCRIPTING::PyScriptingPath( true ).ToStdString();
102 
103  using namespace pybind11::literals;
104  auto locals = pybind11::dict( "sys_path"_a = sys_path,
105  "user_path"_a = user_path );
106 
107  pybind11::exec( R"(
108 import sys
109 import pcbnew
110 pcbnew.LoadPlugins( sys_path, user_path )
111  )", pybind11::globals(), locals );
112  }
113 
114  if( !m_isFootprintEditor )
115  {
116  // Action plugins can be modified, therefore the plugins menu must be updated:
117  frame()->ReCreateMenuBar();
118  // Recreate top toolbar to add action plugin buttons
119  frame()->ReCreateHToolbar();
120  }
121 
122  return 0;
123 }
124 
125 
127 {
128  wxString pluginpath( SCRIPTING::PyPluginsPath( true ) );
129  LaunchExternal( pluginpath );
130 
131  return 0;
132 }
133 
134 
136 {
137 
140 }
int reloadPlugins(const TOOL_EVENT &aEvent)
< Reload Python plugins and reset toolbar (if in pcbnew)
BITMAP2CMP_SETTINGS kiface
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
This file is part of the common library TODO brief description.
void Reset(RESET_REASON aReason) override
Basic initialization.
static TOOL_ACTION pluginsReload
Scripting Actions.
Definition: pcb_actions.h:315
int showPluginFolder(const TOOL_EVENT &aEvent)
Bind handlers to corresponding TOOL_ACTIONs.
void Go(int(T::*aStateFunc)(const TOOL_EVENT &), const TOOL_EVENT_LIST &aConditions=TOOL_EVENT(TC_ANY, TA_ANY))
Define which state (aStateFunc) to go when a certain event arrives (aConditions).
static void UnloadAll()
Unload (deregister) all action plugins.
This file contains miscellaneous commonly used macros and functions.
PCB_BASE_EDIT_FRAME * frame() const
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:96
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
Generic, UI-independent tool event.
Definition: tool_event.h:152
pcbnew DSO
Definition: kiway.h:269
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:195
virtual void ReCreateMenuBar() override
Recreates the menu bar.
bool m_isFootprintEditor
static TOOL_ACTION pluginsShowFolder
Definition: pcb_actions.h:316
bool Init() override
Init() is called once upon a registration of the tool.
Class PCBNEW_ACTION_PLUGINS.
virtual void ReCreateHToolbar()=0
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:148
~SCRIPTING_TOOL()
React to model/view changes.
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:77
void LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
Definition: launch_ext.cpp:25
PyObject *(*)(void) initfunc