Is it possible to pan (and zoom) to a given X/Y location on the board using the pcbnew Python API?
Background: I have created a simple ActionPlugin that checks for return vias, i.e. some kind of custom EMI DRC. Vias without return vias in their vicinity are presented as a list in a dialog window (similar to regular DRC issues). I would like to pan and zoom the pcbnew window’s canvas to the location of the listed via if the corresponding list item is clicked.
Locating the via manually using its listed X/Y position is tedious.
There is FocusOnLocation() from EDA_DRAW_FRAME and FocusOnItem(), but no idea if this is exposed to Python and if how you can get the frame in the Python API.
Do you (or somebody else) know whether there are technical obstacles that prevent the developers from exposing these methods and the frame (I would need the frame ID to let wx look it up, right?) to the Python API?
I guess that pan and zoom could be quite useful features for some Action Plugins.
I suggest you create a feature request on gitlab. There are people that know more than i do.
Do you (or somebody else) know whether there are technical obstacles that prevent the developers from exposing these methods and the frame (I would need the frame ID to let wx look it up, right?) to the Python API?
I don’t know. Maybe you could try it on your system? AFAIK common/swig/kicad.i contains the list of exposed headers. Change it, recompile it, test it.
That might already be possible through wxWidget’s own API. You can import wx and call for example “wx.GetTopLevelWindows()”. Try to find out if you can navigate to the relevant object and call its methods, possibly starting from wx.Frame — wxPython Phoenix 4.2.1 documentation.
I’m interested in such functionality myself, so far I was able to get the canvas window:
def GetCanvas(self) -> wx.Window | None:
window = wx.FindWindowByName("PcbFrame")
found = []
def _find(window):
for child in window.GetChildren():
if child.GetClassInfo().GetClassName() == "wxGLCanvas":
found.append(child)
_find(child)
_find(window)
logger.info(f"Found: {found}")
if found:
return found[0]
return None
I’m using ClassInfo because not all windows have names and ID is unknown.
The returned window is correct because I can:
if canvas := GetCanvas():
canvas.Move(20, 20)
which updates my pcbnew window:
I didn’t figure out yet how to move window contents and not window itself.
I’m a little bit stuck currently. I’m looking ad wx.Window — wxPython Phoenix 4.2.1 documentation API, tried couple of functions, for example Scroll but without success.
I’m under impression that I need to get underlying canvas object and wx.Window is not what I need.
I also saw ExecuteRemoteCommand function in pcb_edit_frame.h:
/**
* Execute a remote command send by Eeschema via a socket, port KICAD_PCB_PORT_SERVICE_NUMBER
* (currently 4242).
*
* This is a virtual function called by EDA_DRAW_FRAME::OnSockRequest().
*
* @param cmdline is the received command from socket.
*/
void ExecuteRemoteCommand( const char* cmdline ) override;
when item is clicked on schematic it gets focused on pcb window, do you think it would be possible to emulate such remote command from python plugin?
I managed to send some commands when pcbnew launched standalone, for example this works:
echo "\$NET: COL2" | nc 127.0.0.1 4242
but indeed, $SELECT (which I determined eeschema is using when selecting element) does not work that way. Both eeschema and pcbnew need to be launched from main launcher but then neither is listening for external commands.
As far as I know, both the schematic editor and PCB editors have become a single program. I once read something about combining the executables to make communication between them easier.
But this also does not compute. When I look at their sizes, they are both about 7.5MB.
paul@cezanne:~$ ls -l /usr/bin/eeschema
-rwxr-xr-x 1 root root 7773688 Aug 14 01:14 /usr/bin/eeschema
paul@cezanne:~$ ls -l /usr/bin/pcbnew
-rwxr-xr-x 1 root root 7769592 Aug 14 01:14 /usr/bin/pcbnew
So now I don’t know if there is some truth in it, or if I’m writing gibberish at the moment.
Most of the application code is in shared libraries. Kicad main app loads them when you launch editors from project manager. So in a sense it’s a combined executable. But there are still separate binaries for eeschema/pcbnew for standalone mode.
I just gave it a try and it works wonderfully with my return via checker plugin. It keeps the zoom level (which the user can dynamically change while the non-modal plugin window stays open) and only pans to the selected item (via in my case). This is exactly what I was looking for.