Footprint wizards management: Now display the list of not loadable footprint wizards in footprint wizard dialog.
Not loadable wizards are Python scripts having a syntax error or are not compatible scripts due to changes in API.
This commit is contained in:
parent
5fee9b2405
commit
56f8e10eb4
|
@ -33,6 +33,7 @@
|
|||
#include <kiface_i.h>
|
||||
#include <dialog_footprint_wizard_list.h>
|
||||
#include <class_footprint_wizard.h>
|
||||
#include <python_scripting.h>
|
||||
|
||||
enum FPGeneratorRowNames
|
||||
{
|
||||
|
@ -75,6 +76,7 @@ DIALOG_FOOTPRINT_WIZARD_LIST::DIALOG_FOOTPRINT_WIZARD_LIST( wxWindow* aParent )
|
|||
m_footprintGeneratorsGrid->SetCellValue( ii, FP_GEN_ROW_DESCR, description );
|
||||
|
||||
}
|
||||
//wxLogMessage( KICAD_FAILED_PLUGINS );
|
||||
|
||||
m_footprintGeneratorsGrid->AutoSizeColumns();
|
||||
|
||||
|
@ -98,6 +100,15 @@ DIALOG_FOOTPRINT_WIZARD_LIST::DIALOG_FOOTPRINT_WIZARD_LIST( wxWindow* aParent )
|
|||
SetSize( size );
|
||||
}
|
||||
|
||||
|
||||
wxString not_loaded_wiz_names;
|
||||
pcbnewGetUnloadableScriptNames( not_loaded_wiz_names );
|
||||
|
||||
if( not_loaded_wiz_names.IsEmpty() )
|
||||
m_bsizerNotLoaded->Show( false );
|
||||
else
|
||||
m_tcNotLoaded->SetValue( not_loaded_wiz_names );
|
||||
|
||||
Center();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version May 6 2016)
|
||||
// C++ code generated with wxFormBuilder (version Dec 4 2016)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
|
@ -11,7 +11,7 @@
|
|||
|
||||
DIALOG_FOOTPRINT_WIZARD_LIST_BASE::DIALOG_FOOTPRINT_WIZARD_LIST_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
|
||||
{
|
||||
this->SetSizeHints( wxSize( 400,200 ), wxDefaultSize );
|
||||
this->SetSizeHints( wxSize( 400,300 ), wxDefaultSize );
|
||||
|
||||
wxBoxSizer* bSizerMain;
|
||||
bSizerMain = new wxBoxSizer( wxVERTICAL );
|
||||
|
@ -50,6 +50,20 @@ DIALOG_FOOTPRINT_WIZARD_LIST_BASE::DIALOG_FOOTPRINT_WIZARD_LIST_BASE( wxWindow*
|
|||
|
||||
bSizerMain->Add( m_footprintGeneratorsGrid, 1, wxALL|wxEXPAND, 5 );
|
||||
|
||||
m_bsizerNotLoaded = new wxBoxSizer( wxVERTICAL );
|
||||
|
||||
m_staticText1 = new wxStaticText( this, wxID_ANY, _("Not loadable:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
m_staticText1->Wrap( -1 );
|
||||
m_bsizerNotLoaded->Add( m_staticText1, 0, wxTOP|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
m_tcNotLoaded = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
|
||||
m_tcNotLoaded->SetMinSize( wxSize( -1,60 ) );
|
||||
|
||||
m_bsizerNotLoaded->Add( m_tcNotLoaded, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
|
||||
|
||||
|
||||
bSizerMain->Add( m_bsizerNotLoaded, 0, wxEXPAND, 5 );
|
||||
|
||||
m_staticline = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
|
||||
bSizerMain->Add( m_staticline, 0, wxEXPAND | wxALL, 5 );
|
||||
|
||||
|
|
|
@ -41,10 +41,10 @@
|
|||
<property name="hidden">0</property>
|
||||
<property name="id">wxID_ANY</property>
|
||||
<property name="maximum_size"></property>
|
||||
<property name="minimum_size">400,200</property>
|
||||
<property name="minimum_size">400,300</property>
|
||||
<property name="name">DIALOG_FOOTPRINT_WIZARD_LIST_BASE</property>
|
||||
<property name="pos"></property>
|
||||
<property name="size">554,286</property>
|
||||
<property name="size">597,339</property>
|
||||
<property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
|
||||
<property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
|
||||
<property name="title">Footprint Generators</property>
|
||||
|
@ -236,6 +236,191 @@
|
|||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxBoxSizer" expanded="1">
|
||||
<property name="minimum_size"></property>
|
||||
<property name="name">m_bsizerNotLoaded</property>
|
||||
<property name="orient">wxVERTICAL</property>
|
||||
<property name="permission">protected</property>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</property>
|
||||
<object class="wxStaticText" 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="label">Not loadable:</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_staticText1</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"></property>
|
||||
<property name="subclass"></property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<property name="wrap">-1</property>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT</property>
|
||||
<property name="proportion">0</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">-1,60</property>
|
||||
<property name="moveable">1</property>
|
||||
<property name="name">m_tcNotLoaded</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">wxTE_MULTILINE|wxTE_READONLY</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>
|
||||
<event name="OnChar"></event>
|
||||
<event name="OnEnterWindow"></event>
|
||||
<event name="OnEraseBackground"></event>
|
||||
<event name="OnKeyDown"></event>
|
||||
<event name="OnKeyUp"></event>
|
||||
<event name="OnKillFocus"></event>
|
||||
<event name="OnLeaveWindow"></event>
|
||||
<event name="OnLeftDClick"></event>
|
||||
<event name="OnLeftDown"></event>
|
||||
<event name="OnLeftUp"></event>
|
||||
<event name="OnMiddleDClick"></event>
|
||||
<event name="OnMiddleDown"></event>
|
||||
<event name="OnMiddleUp"></event>
|
||||
<event name="OnMotion"></event>
|
||||
<event name="OnMouseEvents"></event>
|
||||
<event name="OnMouseWheel"></event>
|
||||
<event name="OnPaint"></event>
|
||||
<event name="OnRightDClick"></event>
|
||||
<event name="OnRightDown"></event>
|
||||
<event name="OnRightUp"></event>
|
||||
<event name="OnSetFocus"></event>
|
||||
<event name="OnSize"></event>
|
||||
<event name="OnText"></event>
|
||||
<event name="OnTextEnter"></event>
|
||||
<event name="OnTextMaxLen"></event>
|
||||
<event name="OnTextURL"></event>
|
||||
<event name="OnUpdateUI"></event>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
</object>
|
||||
<object class="sizeritem" expanded="1">
|
||||
<property name="border">5</property>
|
||||
<property name="flag">wxEXPAND | wxALL</property>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// C++ code generated with wxFormBuilder (version May 6 2016)
|
||||
// C++ code generated with wxFormBuilder (version Dec 4 2016)
|
||||
// http://www.wxformbuilder.org/
|
||||
//
|
||||
// PLEASE DO "NOT" EDIT THIS FILE!
|
||||
|
@ -20,8 +20,10 @@ class DIALOG_SHIM;
|
|||
#include <wx/font.h>
|
||||
#include <wx/grid.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statline.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
|
@ -37,6 +39,9 @@ class DIALOG_FOOTPRINT_WIZARD_LIST_BASE : public DIALOG_SHIM
|
|||
|
||||
protected:
|
||||
wxGrid* m_footprintGeneratorsGrid;
|
||||
wxBoxSizer* m_bsizerNotLoaded;
|
||||
wxStaticText* m_staticText1;
|
||||
wxTextCtrl* m_tcNotLoaded;
|
||||
wxStaticLine* m_staticline;
|
||||
wxStdDialogButtonSizer* m_sdbSizer;
|
||||
wxButton* m_sdbSizerOK;
|
||||
|
@ -48,7 +53,7 @@ class DIALOG_FOOTPRINT_WIZARD_LIST_BASE : public DIALOG_SHIM
|
|||
|
||||
public:
|
||||
|
||||
DIALOG_FOOTPRINT_WIZARD_LIST_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Footprint Generators"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 554,286 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
DIALOG_FOOTPRINT_WIZARD_LIST_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Footprint Generators"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 597,339 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
|
||||
~DIALOG_FOOTPRINT_WIZARD_LIST_BASE();
|
||||
|
||||
};
|
||||
|
|
|
@ -485,7 +485,6 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
|
|||
|
||||
if( !appK2S.FileExists() )
|
||||
GetMenuBar()->FindItem( ID_GEN_EXPORT_FILE_STEP )->Enable( false );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -201,6 +201,37 @@ bool pcbnewInitPythonScripting( const char * aUserScriptingPath )
|
|||
}
|
||||
|
||||
|
||||
void pcbnewGetUnloadableScriptNames( wxString& aNames )
|
||||
{
|
||||
PyLOCK lock;
|
||||
PyErr_Clear();
|
||||
|
||||
PyObject* globals = PyDict_New();
|
||||
PyObject* builtins = PyImport_ImportModule( "pcbnew" );
|
||||
PyDict_SetItemString( globals, "pcbnew", builtins );
|
||||
Py_DECREF( builtins );
|
||||
|
||||
// Execute the code and get the returned data
|
||||
PyObject* localDict = PyDict_New();
|
||||
PyObject* pobj = PyRun_String( "result = pcbnew.GetUnLoadableWizards()",
|
||||
Py_file_input, globals, localDict);
|
||||
Py_DECREF( globals );
|
||||
|
||||
if( pobj )
|
||||
{
|
||||
PyObject* str = PyDict_GetItemString(localDict, "result" );
|
||||
const char* str_res = str ? PyString_AsString( str ) : 0;
|
||||
aNames = FROM_UTF8( str_res );
|
||||
Py_DECREF( pobj );
|
||||
}
|
||||
|
||||
Py_DECREF( localDict );
|
||||
|
||||
if( PyErr_Occurred() )
|
||||
wxLogMessage(PyErrStringWithTraceback());
|
||||
}
|
||||
|
||||
|
||||
void pcbnewFinishPythonScripting()
|
||||
{
|
||||
#ifdef KICAD_SCRIPTING_WXPYTHON
|
||||
|
@ -312,13 +343,17 @@ wxArrayString PyArrayStringToWx( PyObject* aArrayString )
|
|||
{
|
||||
wxArrayString ret;
|
||||
|
||||
int list_size = PyList_Size( aArrayString );
|
||||
if( !aArrayString )
|
||||
return ret;
|
||||
|
||||
for( int n = 0; n<list_size; n++ )
|
||||
int list_size = PyList_Size( aArrayString );
|
||||
|
||||
for( int n = 0; n < list_size; n++ )
|
||||
{
|
||||
PyObject* element = PyList_GetItem( aArrayString, n );
|
||||
|
||||
ret.Add( FROM_UTF8( PyString_AsString( element ) ), 1 );
|
||||
if( element )
|
||||
ret.Add( FROM_UTF8( PyString_AsString( element ) ), 1 );
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -338,17 +373,21 @@ wxString PyErrStringWithTraceback()
|
|||
|
||||
PyErr_Fetch( &type, &value, &traceback );
|
||||
|
||||
PyObject* tracebackModuleString = PyString_FromString( (char*) "traceback" );
|
||||
PyObject* tracebackModule = PyImport_Import( tracebackModuleString );
|
||||
PyObject* tracebackModuleString = PyString_FromString( "traceback" );
|
||||
PyObject* tracebackModule = PyImport_Import( tracebackModuleString );
|
||||
Py_DECREF( tracebackModuleString );
|
||||
|
||||
PyObject* formatException = PyObject_GetAttrString( tracebackModule,
|
||||
"format_exception" );
|
||||
Py_DECREF( tracebackModule );
|
||||
|
||||
PyObject* formatException = PyObject_GetAttrString( tracebackModule,
|
||||
(char*) "format_exception" );
|
||||
PyObject* args = Py_BuildValue( "(O,O,O)", type, value, traceback );
|
||||
|
||||
PyObject* result = PyObject_CallObject( formatException, args );
|
||||
|
||||
Py_DECREF( args );
|
||||
PyObject* args = Py_BuildValue( "(O,O,O)", type, value, traceback );
|
||||
PyObject* result = PyObject_CallObject( formatException, args );
|
||||
Py_XDECREF( formatException );
|
||||
Py_XDECREF( args );
|
||||
Py_XDECREF( type );
|
||||
Py_XDECREF( value );
|
||||
Py_XDECREF( traceback );
|
||||
|
||||
wxArrayString res = PyArrayStringToWx( result );
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
bool pcbnewInitPythonScripting( const char * aUserScriptingPath );
|
||||
void pcbnewFinishPythonScripting();
|
||||
|
||||
void pcbnewGetUnloadableScriptNames( wxString& aNames );
|
||||
|
||||
#ifdef KICAD_SCRIPTING_WXPYTHON
|
||||
|
||||
|
|
|
@ -52,7 +52,18 @@
|
|||
%pythoncode
|
||||
{
|
||||
|
||||
KICAD_PLUGINS={}
|
||||
KICAD_PLUGINS={} # the list of loaded footprint wizards
|
||||
|
||||
""" the list of not loaded python scripts (due to a synthax error in python script)
|
||||
this is the python script full filenames, separated by '\n'
|
||||
"""
|
||||
NOT_LOADED_WIZARDS=""
|
||||
|
||||
|
||||
def GetUnLoadableWizards():
|
||||
global NOT_LOADED_WIZARDS
|
||||
return NOT_LOADED_WIZARDS
|
||||
|
||||
|
||||
def ReloadPlugin(name):
|
||||
if not KICAD_PLUGINS.has_key(name):
|
||||
|
@ -133,6 +144,8 @@ def LoadPlugins(bundlepath=None):
|
|||
plugin_directories.append(os.environ['HOME']+'/.kicad/scripting/')
|
||||
plugin_directories.append(os.environ['HOME']+'/.kicad/scripting/plugins/')
|
||||
|
||||
failed_wizards_list=""
|
||||
|
||||
for plugins_dir in plugin_directories:
|
||||
if not os.path.isdir(plugins_dir):
|
||||
continue
|
||||
|
@ -147,18 +160,24 @@ def LoadPlugins(bundlepath=None):
|
|||
continue
|
||||
|
||||
try: # If there is an error loading the script, skip it
|
||||
module_filename = plugins_dir + "/" + module
|
||||
mod = __import__(module[:-3], locals(), globals())
|
||||
|
||||
module_filename = plugins_dir+"/"+module
|
||||
mtime = os.path.getmtime(module_filename)
|
||||
|
||||
if hasattr(mod,'register'):
|
||||
KICAD_PLUGINS[module]={"filename":module_filename,
|
||||
"modification_time":mtime,
|
||||
"object":mod.register(),
|
||||
"module":mod}
|
||||
except:
|
||||
if failed_wizards_list != "" :
|
||||
failed_wizards_list += "\n"
|
||||
failed_wizards_list += module_filename
|
||||
pass
|
||||
|
||||
global NOT_LOADED_WIZARDS
|
||||
NOT_LOADED_WIZARDS = failed_wizards_list
|
||||
|
||||
|
||||
class KiCadPlugin:
|
||||
def __init__(self):
|
||||
|
@ -189,8 +208,6 @@ class KiCadPlugin:
|
|||
return
|
||||
|
||||
|
||||
|
||||
|
||||
class FilePlugin(KiCadPlugin):
|
||||
def __init__(self):
|
||||
KiCadPlugin.__init__(self)
|
||||
|
@ -355,6 +372,7 @@ class FootprintWizardParameter(object):
|
|||
|
||||
return s
|
||||
|
||||
|
||||
class FootprintWizardPlugin(KiCadPlugin, object):
|
||||
def __init__(self):
|
||||
KiCadPlugin.__init__(self)
|
||||
|
|
Loading…
Reference in New Issue