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 <python_scripting.h>
31#include <tools/pcb_actions.h>
32
33#include <pybind11/eval.h>
34
35#include <Python.h>
36#include <wx/string.h>
37#include <launch_ext.h>
38
39using initfunc = PyObject* (*)(void);
40
42 PCB_TOOL_BASE( "pcbnew.ScriptingTool" )
43{}
44
45
47{}
48
49
51{
52}
53
54
56{
57 PyLOCK lock;
58 std::string pymodule( "_pcbnew" );
59
60 if( !SCRIPTING::IsModuleLoaded( pymodule ) )
61 {
63 initfunc pcbnew_init = reinterpret_cast<initfunc>( kiface->IfaceOrAddress( KIFACE_SCRIPTING_LEGACY ) );
64 PyImport_AddModule( pymodule.c_str() );
65 PyObject* mod = pcbnew_init();
66 PyObject* sys_mod = PyImport_GetModuleDict();
67 PyDict_SetItemString( sys_mod, "_pcbnew", mod );
68 Py_DECREF( mod );
69
70 // plugins will be loaded later via ReloadPlugins()
71 }
72
73 return true;
74}
75
76
78{
79 // Reload Python plugins if they are newer than the already loaded, and load new plugins
80 // Remove all action plugins so that we don't keep references to old versions
82
83 try
84 {
85 PyLOCK lock;
87 }
88 catch( ... )
89 {}
90}
91
92
94{
95 // Reload Python plugins if they are newer than the already loaded, and load new plugins
96 // Remove all action plugins so that we don't keep references to old versions
98
99 try
100 {
101 PyLOCK lock;
103 }
104 catch( ... )
105 {
106 return -1;
107 }
108
110 {
111 // Action plugins can be modified, therefore the plugins menu must be updated:
113 // Recreate top toolbar to add action plugin buttons
115 // Post a size event to force resizing toolbar by the AUI manager:
116 frame()->PostSizeEvent();
117 }
118
119 return 0;
120}
121
122
124{
125 // Load pcbnew inside Python and load all the user plugins and package-based plugins
126 using namespace pybind11::literals;
127
128 auto locals = pybind11::dict(
129 "sys_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( SCRIPTING::PATH_TYPE::STOCK ) ),
130 "user_path"_a = TO_UTF8( SCRIPTING::PyScriptingPath( SCRIPTING::PATH_TYPE::USER ) ),
131 "third_party_path"_a =
132 TO_UTF8( SCRIPTING::PyPluginsPath( SCRIPTING::PATH_TYPE::THIRDPARTY ) ) );
133
134 pybind11::exec( R"(
135import sys
136import pcbnew
137pcbnew.LoadPlugins( sys_path, user_path, third_party_path )
138 )",
139 pybind11::globals(), locals );
140}
141
142
144{
145 wxString pluginpath( SCRIPTING::PyPluginsPath( SCRIPTING::PATH_TYPE::USER ) );
146 LaunchExternal( pluginpath );
147}
148
149
151{
153 return 0;
154}
155
156
158{
161}
Class PCBNEW_ACTION_PLUGINS.
static void UnloadAll()
Unload (deregister) all action plugins.
void ReCreateMenuBar()
Recreates the menu bar.
virtual void ReCreateHToolbar()
KIWAY & Kiway() const
Return a reference to the KIWAY that this object has an opportunity to participate in.
Definition: kiway_holder.h:53
virtual KIFACE * KiFACE(FACE_T aFaceId, bool doLoad=true)
Return the KIFACE* given a FACE_T.
Definition: kiway.cpp:202
@ FACE_PCB
pcbnew DSO
Definition: kiway.h:287
static TOOL_ACTION pluginsShowFolder
Definition: pcb_actions.h:403
static TOOL_ACTION pluginsReload
Scripting Actions.
Definition: pcb_actions.h:402
PCB_BASE_EDIT_FRAME * 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
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:391
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)