Draft: Reimplement halshow in Python#4231
Conversation
Replace the Tcl/Tk halshow (tcl/bin/halshow.tcl) with a Python/Qt
implementation using qtpy for cross-backend compatibility. The new
edition provides identical functionality plus additional features:
Core architecture:
- Direct shared memory access via _hal C extension, eliminating
subprocess overhead. Creates a minimal component "_halshow_{pid}"
that is cleanly removed on exit (ready() -> exit()) to prevent
zombie accumulation.
- Added get_info_components(), get_info_functions(),
get_info_threads() to halmodule.cc for SHM-based listing of
components/functions/threads without halcmd subprocess calls.
- Robust cleanup: atexit handler + signal handlers (SIGINT/SIGTERM/SIGHUP)
ensure component is removed from SHM on any exit path. Fixed a bug where
the old Tcl edition leaked components when exiting via SIGPIPE or
"linuxcnc -l" (which raises SystemExit).
Watch tab:
- Value|Name|Buttons layout matching Tcl halshow order
- Full pin names shown in watch rows (not truncated)
- [Tgl]/[Set]/[Clr] buttons for writable bit signals, plain value for read-only
- Buttons dynamically disabled when signal gains writers at runtime
- Halcmd fallback for writer detection on old _hal.so lacking WRITERS field
Show tab:
- Signal detail matches halcmd "show sig" monospace table format exactly
- Value right-aligned in 5-char field, matching Tcl edition
- Tree view uses monospace font with no word wrap
Main window layout:
- Tree view and tabs side-by-side in a splitter
- Command entry and status bar span full width below the splitter (Tcl match)
- All user-facing GUI text translatable via PO files / gettext (_() wrappers)
This patch was created with help from OpenCode using local llama.cpp
server with Qwen 3.6.
…zation Add a new GRAPH tab (between WATCH and SETTINGS) that renders HAL topology as a bipartite graph (component → signal → component), laid out by Graphviz dot. Graph data model: - GraphDataBuilder collects pins/signals from SHM into structured component/signal dicts, with O(1) pin-to-component index for fast edge resolution - Three-tier fallback for resolving signal connections: pure-SHM pin SIGNAL field, _hal.get_signal_connections(), or halcmd show sig via background QThread - Owner detection falls back to heuristics when old _hal.so lacks OWNER field Layout engine (GraphLayout.compute): - Builds directed AGraph with component boxes and diamond-shaped signal nodes - Runs dot for crossing-minimized placement; extracts edge splines for rendering - Coordinates scaled from points (72 dpi) to device pixels (96 dpi) Rendering (QGraphicsView scene): - ComponentItem: rounded rectangles with blue header, green IN pins (left column), red OUT pins (right column), and connection markers on edges - SignalNodeItem: orange diamonds sized to fit signal names - Edges route from writer pin → signal diamond perimeter → reader pin marker, each segment with arrowhead; uses dot splines when available, cubic bezier fallback - Multi-edge spreading between same component pair Interaction: - Pan via middle/left mouse drag; zoom via scroll wheel or +/- buttons - Right-click context menus on components (add pins to watch) and edges (watch signal) - "Hide unused pins" toggle filters component boxes to only connected pins - Lazy layout computation deferred until first tab activation CLI --dotty flag: - Print HAL topology as DOT source to stdout then exit, with layout parameters matching the GRAPH tab for debugging purposes This patch was created with help from OpenCode using local llama.cpp server with Qwen 3.6.
|
You might want to enable the executable bit in git for halshow.py |
|
[Luca Toniolo]
You might want to enable the executable bit in git for halshow.py
Yes, and integrate it into the build system and install rules.
I did quick testing, not looked at the graph yet, should pygraphviz
become a dependency?
Yes, it is a dependency for the graph drawing.
The grouped view of pins and parameters is the new default, but seems
not working in the port?
What is this? I do not believe I have used or seen this myself.
Something from after 2.9?
…--
Happy hacking
Petter Reinholdtsen
|
Yes, just made it in 2.10 a few weeks back, see #4147 |
In PyQt6 and PySide6, WindowStaysOnTop moved from Qt to Qt.WindowType. Add a compatibility shim that resolves the flag for both backend families. Fixes crash when applying settings (alwaysOnTop toggle) in halshow.py. This patch was created with help from OpenCode using local llama.cpp server with Qwen 3.6.
|
[Luca Toniolo]
Yes, just made it in 2.10 a few weeks back, see #4147
Right. Then I understand. It had an option in the settings tab, set to
true by default. There was a bug in the settings tab, now fixed, making
it impossible to flip the switch. Added the option as I was surprised
the tree did not look the way I was used to, but could drop it if the
new wanted default is the combined pin/parameter tree.
…--
Happy hacking
Petter Reinholdtsen
|
|
Nice! It needs some fine tuning, but most of the features of the current halshow I can find 👍 Some notes:
|
|
[Hans Unzner]
Two more need fixing ;-)
Fixing. How do you trigger these errors? My tests using Python 3.13.5
do not show these problems.
…--
Happy hacking
Petter Reinholdtsen
|
2a433c3 to
78c82ae
Compare
Python 3.11.2 on Bookworm
Sorry I was talking about right-click: halshow-crash.mp4 |
What value did you expect (does halshow show)? |
Well, it shows a float, like 5.325 |
I get a float display. Probably the value is too large to fit into the column width, so the end is cut. |
Yes, seems to be missing formatting. As hansu already mentioned, the graph takes a lot of panning and zooming so having the mouse scroll wheel not supported for zooming is real pain. To make the graph more compact I would drop the extra nodes for the signal names and show those when selecting the line. IMO the biggest problem with these hal graphs is that they very quickly become too large and unwieldy. |
|
A decent solution I found on a similar tool I experimented with, was filtering by the relevant pin to visualize, plus a selection for connections branching, that should filter everything connected to what you are wanting to see without including everything that's not relevant. |
SHOW tab: - Compact one-line-per-item tables matching halcmd visual format - One table per section (pins/params/signals) with aligned columns - Clicking non-leaf tree nodes expands and shows all underlying items - Signal connection info works with old _hal.so lacking SIGNAL SHM field via halcmd subprocess fallback (batched single call for efficiency) - Fixed reversed signal arrow directions: OUT pins show ==>, IN pins <== - Context menu always shows all items (Tcl-style), tooltip at click when nothing selected, right-click no longer crashes WATCH tab: - Column headers (Value / Name) with draggable separator to resize columns - Value column default width 150px, values left-aligned - Boolean bit indicator circles left-aligned within value area - Param leaves render in brown color (Tcl match), sig labels in blue - Context menu on empty space: add from clipboard/HAL text, erase watchlist GRAPH tab: - Mouse wheel zoom centered on cursor position - Keyboard +/- keys for zoom in/out General: - Preferences path displayed with ~ notation instead of full home directory This patch was created with help from OpenCode using local llama.cpp server with Qwen 3.6.
|
I've updated the python edition slightly:
halshow.py: major improvements to SHOW, WATCH, and GRAPH tabs
SHOW tab:
- Compact one-line-per-item tables matching halcmd visual format
- One table per section (pins/params/signals) with aligned columns
- Clicking non-leaf tree nodes expands and shows all underlying items
- Signal connection info works with old _hal.so lacking SIGNAL SHM field
via halcmd subprocess fallback (batched single call for efficiency)
- Fixed reversed signal arrow directions: OUT pins show ==>, IN pins <==
- Context menu always shows all items (Tcl-style), tooltip at click when
nothing selected, right-click no longer crashes
WATCH tab:
- Column headers (Value / Name) with draggable separator to resize columns
- Value column default width 150px, values left-aligned
- Boolean bit indicator circles left-aligned within value area
- Param leaves render in brown color (Tcl match), sig labels in blue
- Context menu on empty space: add from clipboard/HAL text, erase watchlist
GRAPH tab:
- Mouse wheel zoom centered on cursor position
- Keyboard +/- keys for zoom in/out
General:
- Preferences path displayed with ~ notation instead of full home directory
This patch was created with help from OpenCode using local llama.cpp
server with Qwen 3.6.
[Hans Unzner]
- The expand/collapse button for the tree view is missing
I do not understand what you mean? I only see these options in the
menu in the tcl edition, and the same is the case with the python
edition.
- Very good idea to integrate the graphviz graph. But it's very hard to see
the small boxes. Maybe you can get some inspiration from:
https://github.com/multigcs/halviewer (or just integrate that one)
I did not try to improve the graph yet, and will have a look at this
when I have time to look at the graph layout again. I agree that the
graph of real machine HAL setup is confusing and hard to figure out. It
is true also for my own machine, and thus a motivation to come up with a
better graph approach. When that is said, I have already found the
current graph useful when looking at the setup of my own machine,
despite being slightly painful to find the relevant part by panning and
zooming in and out to try to find the relevant part of the graph. :)
[Sigma1912]
To make the graph more compact I would drop the extra nodes for the
signal names and show those when selecting the line.
I decided against this as signals must be represented as one to many
connections, and a single line can not represent this well.
…--
Happy hacking
Petter Reinholdtsen
|
|
@petterreinholdtsen can those changes be added to #4251 |
|
[Rene Hopf]
@petterreinholdtsen can those changes be added to
#4251
I assume so. The changes is quite simple to make more information
available quicker, no real algoritm involved.
…--
Happy hacking
Petter Reinholdtsen
|




Replace the tcl/tk implementation of halshow with a Python/Qt implementation, and add new graph support using graphviz to show the interconnection in HAL between pins and signals.