KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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 AUTHORS.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 <kiface_ids.h>
28#include <kiway.h>
29#include <macros.h>
30#include <pgm_base.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#ifdef KICAD_IPC_API
42#endif
43
44using initfunc = PyObject* (*)(void);
45
47 PCB_TOOL_BASE( "pcbnew.ScriptingTool" )
48{}
49
50
52{}
53
54
56{
57}
58
59
61{
62 PyLOCK lock;
63 std::string pymodule( "_pcbnew" );
64
65 if( !SCRIPTING::IsModuleLoaded( pymodule ) )
66 {
67 KIFACE* kiface = frame()->Kiway().KiFACE( KIWAY::FACE_PCB );
68 initfunc pcbnew_init = reinterpret_cast<initfunc>( kiface->IfaceOrAddress( KIFACE_SCRIPTING_LEGACY ) );
69 PyImport_AddModule( pymodule.c_str() );
70 PyObject* mod = pcbnew_init();
71 PyObject* sys_mod = PyImport_GetModuleDict();
72 PyDict_SetItemString( sys_mod, "_pcbnew", mod );
73 Py_DECREF( mod );
74
75 // plugins will be loaded later via ReloadPlugins()
76 }
77
78 return true;
79}
80
81
83{
84 // Reload Python plugins if they are newer than the already loaded, and load new plugins
85 // Remove all action plugins so that we don't keep references to old versions
87
88 try
89 {
90 PyLOCK lock;
92 }
93 catch( ... )
94 {}
95}
96
97
99{
100 // Reload Python plugins if they are newer than the already loaded, and load new plugins
101 // Remove all action plugins so that we don't keep references to old versions
103
104 try
105 {
106 PyLOCK lock;
108 }
109 catch( ... )
110 {
111 return -1;
112 }
113
114#ifdef KICAD_IPC_API
115 // TODO move this elsewhere when SWIG plugins are removed
116 Pgm().GetPluginManager().ReloadPlugins();
117#endif
118
120 {
121 // Action plugins can be modified, therefore the plugins menu must be updated:
122 frame()->ReCreateMenuBar();
123 // Recreate top toolbar to add action plugin buttons
124 frame()->ReCreateHToolbar();
125 // Post a size event to force resizing toolbar by the AUI manager:
126 frame()->PostSizeEvent();
127 }
128
129 return 0;
130}
131
132
134{
135 // Load pcbnew inside Python and load all the user plugins and package-based plugins
136 using namespace pybind11::literals;
137
138 auto locals = pybind11::dict(
139 "sys_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( SCRIPTING::PATH_TYPE::STOCK ) ),
140 "user_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( SCRIPTING::PATH_TYPE::USER ) ),
141 "third_party_path"_a =
142 TO_UTF8( SCRIPTING::PyPluginsPath( SCRIPTING::PATH_TYPE::THIRDPARTY ) ) );
143
144 pybind11::exec( R"(
145import sys
146import pcbnew
147pcbnew.LoadPlugins( sys_path, user_path, third_party_path )
148 )",
149 pybind11::globals(), locals );
150}
151
152
154{
155 wxString pluginpath( SCRIPTING::PyPluginsPath( SCRIPTING::PATH_TYPE::USER ) );
156 LaunchExternal( pluginpath );
157}
158
159
161{
163 return 0;
164}
165
166
168{
171}
Class PCBNEW_ACTION_PLUGINS.
static TOOL_ACTION pluginsReload
Definition: actions.h:241
static void UnloadAll()
Unload (deregister) all action plugins.
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:292
static TOOL_ACTION pluginsShowFolder
Scripting Actions.
Definition: pcb_actions.h:418
T * frame() const
bool m_isFootprintEditor
int reloadPlugins(const TOOL_EVENT &aEvent)
< Reload Python plugins and reset toolbar (if in pcbnew)
~SCRIPTING_TOOL()
React to model/view changes.
void Reset(RESET_REASON aReason) override
Basic initialization.
bool Init() override
Init() is called once upon a registration of the tool.
static void callLoadPlugins()
Open the user's plugin folder in the system browser.
int showPluginFolder(const TOOL_EVENT &aEvent)
Bind handlers to corresponding TOOL_ACTIONs.
static void ShowPluginFolder()
static void ReloadPlugins()
void setTransitions() override
This method is meant to be overridden in order to specify handlers for events.
RESET_REASON
Determine the reason of reset for a tool.
Definition: tool_base.h:78
Generic, UI-independent tool event.
Definition: tool_event.h:167
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).
@ KIFACE_SCRIPTING_LEGACY
Definition: kiface_ids.h:57
bool LaunchExternal(const wxString &aPath)
Launches the given file or folder in the host OS.
Definition: launch_ext.cpp:25
This file contains miscellaneous commonly used macros and functions.
PyObject *(*)(void) initfunc
PGM_BASE & Pgm()
The global Program "get" accessor.
Definition: pgm_base.cpp:1060
see class PGM_BASE
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:398
void * IfaceOrAddress(int aDataId) override
Return a pointer to the requested object.
Implement a participant in the KIWAY alchemy.
Definition: kiway.h:151
IFACE KIFACE_BASE kiface("pcb_test_frame", KIWAY::FACE_PCB)