KiCad scripting plugin architecture, footprint wizards first

This commit is contained in:
Miguel Angel Ajo 2012-05-05 22:18:47 +02:00
parent f114e800a4
commit edee5dc1ce
9 changed files with 476 additions and 13 deletions

View File

@ -231,14 +231,15 @@ set(PCBNEW_COMMON_SRCS
# Scripting sources
##
if (KICAD_SCRIPTING)
set(PCBNEW_SCRIPTING_PYTHON_HELPERS
set(PCBNEW_SCRIPTING_PYTHON_HELPERS
../scripting/wx_python_helpers.cpp
../scripting/python_scripting.cpp
scripting/pcbnew_scripting_helpers.cpp
scripting/pcbnew_footprint_wizards.cpp
)
if (KICAD_SCRIPTING)
set(PCBNEW_SCRIPTING_SRCS
pcbnew_wrap.cxx
${PCBNEW_SCRIPTING_PYTHON_HELPERS}
@ -279,6 +280,7 @@ if (KICAD_SCRIPTING)
DEPENDS scripting/board.i
DEPENDS scripting/board_item.i
DEPENDS scripting/module.i
DEPENDS scripting/plugins.i
DEPENDS scripting/units.i
DEPENDS ../scripting/dlist.i
DEPENDS ../scripting/kicad.i

View File

@ -133,5 +133,7 @@
%include "board.i"
%include "module.i"
%include "plugins.i"
%include "units.i"

View File

@ -0,0 +1,179 @@
/**
* @file pcbnew_footprint_wizards.cpp
* @brief Class PCBNEW_FOOTPRINT_WIZARDS
*/
#include "pcbnew_footprint_wizards.h"
#include <stdio.h>
FOOTPRINT_WIZARD::FOOTPRINT_WIZARD(PyObject *aWizard)
{
this->py_wizard = aWizard;
Py_XINCREF(aWizard);
}
FOOTPRINT_WIZARD::~FOOTPRINT_WIZARD()
{
Py_XDECREF(this->py_wizard);
}
PyObject* FOOTPRINT_WIZARD::CallMethod(const char* aMethod, PyObject *aArglist)
{
PyObject *pFunc;
/* pFunc is a new reference to the desired method */
pFunc = PyObject_GetAttrString(this->py_wizard, aMethod);
if (pFunc && PyCallable_Check(pFunc))
{
PyObject *result;
result = PyObject_CallObject(pFunc, aArglist);
if (PyErr_Occurred())
{
PyObject *t, *v, *b;
PyErr_Fetch(&t, &v, &b);
printf ("calling %s()\n",aMethod);
printf ("Exception: %s\n",PyString_AsString(PyObject_Str(v)));
printf (" : %s\n",PyString_AsString(PyObject_Str(b)));
}
if (result)
{
Py_XDECREF(pFunc);
return result;
}
}
else
{
printf("method not found, or not callable: %s\n",aMethod);
}
if (pFunc) Py_XDECREF(pFunc);
return NULL;
}
wxString FOOTPRINT_WIZARD::CallRetStrMethod(const char* aMethod, PyObject *aArglist)
{
wxString ret;
PyObject *result = CallMethod(aMethod,aArglist);
if (result)
{
const char *str_res = PyString_AsString(result);
ret = wxString::FromUTF8(str_res);
Py_DECREF(result);
}
else
{
printf("method not found, or not callable: %s\n",aMethod);
}
return ret;
}
wxString FOOTPRINT_WIZARD::GetName()
{
return CallRetStrMethod("GetName");
}
wxString FOOTPRINT_WIZARD::GetImage()
{
return CallRetStrMethod("GetImage");
}
wxString FOOTPRINT_WIZARD::GetDescription()
{
return CallRetStrMethod("GetDescription");
}
int FOOTPRINT_WIZARD::GetNumParameterPages()
{
int ret;
PyObject *result;
/* Time to call the callback */
result = CallMethod("GetNumParameterPages",NULL);
if (result)
{
if (!PyInt_Check(result)) return -1;
ret = PyInt_AsLong(result);
Py_DECREF(result);
}
return ret;
}
wxString FOOTPRINT_WIZARD::GetParameterPageName(int aPage)
{
wxString ret;
PyObject *arglist;
PyObject *result;
/* Time to call the callback */
arglist = Py_BuildValue("(i)", aPage);
result = CallMethod("GetParameterPageName",arglist);
Py_DECREF(arglist);
if (result)
{
const char *str_res = PyString_AsString(result);
ret = wxString::FromUTF8(str_res);
Py_DECREF(result);
}
return ret;
}
wxArrayString FOOTPRINT_WIZARD::GetParameterNames(int aPage)
{
wxArrayString a;
return a;
}
wxArrayString FOOTPRINT_WIZARD::GetParameterValues(int aPage)
{
wxArrayString a;
return a;
}
wxString FOOTPRINT_WIZARD::SetParameterValues(int aPage,wxArrayString& aValues)
{
wxString ret;
return ret;
}
MODULE FOOTPRINT_WIZARD::*GetModule()
{
return NULL;
}
std::vector<FOOTPRINT_WIZARD*> FOOTPRINT_WIZARDS::m_FootprintWizards;
void FOOTPRINT_WIZARDS::register_wizard(PyObject* wizard)
{
FOOTPRINT_WIZARD *fw;
fw = new FOOTPRINT_WIZARD(wizard);
m_FootprintWizards.push_back(fw);
printf("Registered python footprint wizard '%s'\n",
(const char*)fw->GetName().mb_str());
int pages = fw->GetNumParameterPages();
printf(" %d pages\n",pages);
for (int n=0; n<pages; n++)
{
printf(" page %d->'%s'\n",n,
(const char*)fw->GetParameterPageName(n).mb_str());
}
}

View File

@ -0,0 +1,45 @@
/**
* @file pcbnew_footprint_wizards.h
* @brief Class PCBNEW_FOOTPRINT_WIZARDS
*/
#ifndef PCBNEW_FOOTPRINT_WIZARDS_H
#define PCBNEW_FOOTPRINT_WIZARDS_H
#include <Python.h>
#include <vector>
#include <wxPcbStruct.h>
class FOOTPRINT_WIZARD
{
PyObject *py_wizard;
PyObject *CallMethod(const char *aMethod, PyObject *aArglist=NULL);
wxString CallRetStrMethod(const char *aMethod, PyObject *aArglist=NULL);
public:
FOOTPRINT_WIZARD(PyObject *wizard);
~FOOTPRINT_WIZARD();
wxString GetName();
wxString GetImage();
wxString GetDescription();
int GetNumParameterPages();
wxString GetParameterPageName(int aPage);
wxArrayString GetParameterNames(int aPage);
wxArrayString GetParameterValues(int aPage);
wxString SetParameterValues(int aPage,wxArrayString& aValues);
MODULE *GetModule();
};
class FOOTPRINT_WIZARDS
{
private:
static std::vector<FOOTPRINT_WIZARD*> m_FootprintWizards;
public:
static void register_wizard(PyObject *wizard);
};
#endif /* PCBNEW_FOOTPRINT_WIZARDS_H */

View File

@ -0,0 +1,11 @@
%{
#include <scripting/pcbnew_footprint_wizards.h>
%}
class FOOTPRINT_WIZARDS
{
public:
static void register_wizard(PyObject *wizard);
};

View File

@ -0,0 +1,83 @@
#!/usr/bin/python
from pcbnew import *
class FPCFootprintWizard(FootprintWizardPlugin):
def __init__(self):
FootprintWizardPlugin.__init__(self)
self.name = "FPC"
self.description = "FPC Footprint Wizard"
self.parameters = {
"Pads":
{"n":40,"pitch":0.5,"width":0.25,"height":1.6},
"Shield":
{"shield_to_pad":1.6,"from_top":1.3,"width":1.5,"height":2}
}
def smdRectPad(self,module,size,pos,name):
pad = D_PAD(module)
pad.SetSize(size)
pad.SetShape(PAD_RECT)
pad.SetAttribute(PAD_SMD)
pad.SetLayerMask(PAD_SMD_DEFAULT_LAYERS)
pad.SetPos0(pos)
pad.SetPadName(name)
return pad
def BuildFootprint(self):
pads = self.parameters["Pads"]["n"]
pad_width = self.parameters["Pads"]["width"]
pad_height = self.parameters["Pads"]["height"]
pad_pitch = self.parameters["Pads"]["pitch"]
shl_width = self.parameters["Shield"]["width"]
shl_height = self.parameters["Shield"]["height"]
shl_to_pad = self.parameters["Shield"]["shield_to_pad"]
shl_from_top = self.parameters["Shield"]["from_top"]
size_pad = wxSizeMM(pad_width,pad_height)
size_shld = wxSizeMM(shl_width,shl_height)
# create a new module, it's parent is our previously created pcb
module = MODULE(None)
module.SetReference("FPC"+str(pads)) # give it a reference name
module.m_Reference.SetPos0(wxPointMM(-1,-1))
# create a pad array and add it to the module
for n in range (0,pads):
pad = self.smdRectPad(module,size_pad,wxPointMM(pad_pitch*n,0),str(n+1))
module.Add(pad)
pad_s0 = self.smdRectPad(module,
size_shld,
wxPointMM(-shl_to_pad,shl_from_top),
"0")
pad_s1 = self.smdRectPad(module,
size_shld,
wxPointMM((pads-1)*pad_pitch+shl_to_pad,shl_from_top),
"0")
module.Add(pad_s0)
module.Add(pad_s1)
e = EDGE_MODULE(module)
e.SetStart0(wxPointMM(-1,0))
e.SetEnd0(wxPointMM(0,0))
e.SetWidth(FromMM(0.2))
e.SetLayer(EDGE_LAYER)
e.SetShape(S_SEGMENT)
module.Add(e)
# save the PCB to disk
module.SetLibRef("FPC"+str(pads))
self.module = module
# create our footprint wizard
fpc_wizard = FPCFootprintWizard()
# register it into pcbnew
fpc_wizard.register()

View File

@ -110,3 +110,4 @@
/* std template mappings */
%template(intVector) std::vector<int>;
%include "kicadplugins.i"

147
scripting/kicadplugins.i Normal file
View File

@ -0,0 +1,147 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 NBEE Embedded Systems, Miguel Angel Ajo <miguelangel@nbee.es>
* Copyright (C) 1992-2012 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
*/
%pythoncode
{
# KiCadPlugin base class will register any plugin into the right place
class KiCadPlugin:
def __init__(self):
pass
def register(self):
if isinstance(self,FilePlugin):
pass # register to file plugins in C++
if isinstance(self,FootprintWizardPlugin):
FOOTPRINT_WIZARDS.register_wizard(self)
return
if isinstance(self,ActionPlugin):
pass # register to action plugins in C++
return
# This will be the file io scripting based plugins class
class FilePlugin(KiCadPlugin):
def __init__(self):
KiCadPlugin.__init__(self)
# Scriping footprint wizards
class FootprintWizardPlugin(KiCadPlugin):
def __init__(self):
KiCadPlugin.__init__(self)
self.defaults()
def defaults(self):
self.module = None
self.parameters = {}
self.name = "Undefined Footprint Wizard plugin"
self.description = ""
self.image = ""
def GetName(self):
return self.name
def GetImage(self):
return self.image
def GetDescription(self):
return self.description
def GetNumParameterPages(self):
return len(self.parameters)
def GetParameterPageName(self,page_n):
return self.parameters.keys()[page_n]
def GetParameterNames(self,page_n):
name = self.GetParameterPageName(page_n)
return self.parameters[name].keys()
def GetParameterValues(self,page_n):
name = self.GetParameterPageName(page_n)
return self.parameters[name].keys()
def GetParameterValues(self,page_n):
name = self.GetParameterPageName(page_n)
return self.parameters[name].values()
def SetParameterValues(self,page_n,values):
name = self.GetParameterPageName(pagen_n)
keys = self.parameters[name].values()
n=0
for key in keys:
self.parameters[name][key] = values[n]
n+=1
def GetModule(self):
self.BuildFootprint()
return self.module
def BuildFootprint(self):
return
def Show(self):
print "Footprint Wizard Name: ",self.GetName()
print "Footprint Wizard Description: ",self.GetDescription()
n_pages = self.GetNumParameterPages()
print " setup pages: ",n_pages
for page in range(0,n_pages):
name = self.GetParameterPageName(page)
values = self.GetParameterValues(page)
names = self.GetParameterNames(page)
print "page %d) %s"%(page,name)
for n in range (0,len(values)):
print "\t%s\t:\t%s"%(names[n],values[n])
class ActionPlugin(KiCadPlugin):
def __init__(self):
KiCadPlugin.__init__(self)
def LoadPlugins():
import os
import sys
plugins_dir = os.environ['HOME']+'/.kicad_plugins/'
sys.path.append(plugins_dir)
for module in os.listdir(plugins_dir):
if os.path.isdir(plugins_dir+module):
__import__(module, locals(), globals())
if module == '__init__.py' or module[-3:] != '.py':
continue
__import__(module[:-3], locals(), globals())
}

View File

@ -90,15 +90,6 @@ void pcbnewInitPythonScripting()
swigAddModules();
swigSwitchPythonBuiltin();
#if 0
/* print the list of modules available from python */
while(PyImport_Inittab[i].name)
{
printf("name[%d]=>%s\n",i,PyImport_Inittab[i].name);
i++;
}
#endif
Py_Initialize();
/* setup the scripting path, we may need to add the installation path
@ -106,7 +97,9 @@ void pcbnewInitPythonScripting()
PyRun_SimpleString("import sys\n"
"sys.path.append(\".\")\n"
"import pcbnew\n");
"import pcbnew\n"
"pcbnew.LoadPlugins()"
);
}