plesty.lib.ui.qt.shell
The PLESTY shell: one home window hosting rearrangeable sub-windows.
The shell is a home window with no fixed content of its own. Every
Panel becomes a sub-window the operator owns:
drag it to another edge, drop it onto another panel to tab the two together,
drag the handle between two panels to change how the space is split, drag it
out of the window entirely to get a free-floating window on a second screen,
and drag it back in when the bench gets crowded. Closed panels come back from
the Panels menu; the arrangement is saved on exit and restored next time, so
each rig keeps the layout its operator built.
shell = Shell("Demo", interval_ms=500)
shell.add(spectrum_panel, area="top")
shell.add(map_panel, area="top")
shell.add(power_panel, area="top")
shell.start_recording("run.mp4") # optional: the run as a video
shell.start()
Everything visual comes from Theme — the shell
holds no colour of its own.
Attributes
Classes
Title bar of a sub-window: state dot, title, live status, controls. |
|
One sub-window of the shell, wrapping a |
|
Home window hosting every panel as a rearrangeable sub-window. |
Functions
|
Return a filesystem-safe slug for a shell title. |
|
Re-apply the stylesheet after a dynamic property changed. |
Module Contents
- plesty.lib.ui.qt.shell._AREAS
- plesty.lib.ui.qt.shell._ORIENTATIONS
- plesty.lib.ui.qt.shell.LAYOUT_VERSION = 1
- plesty.lib.ui.qt.shell._slug(text: str) str
Return a filesystem-safe slug for a shell title.
- Parameters:
text (str)
- Return type:
str
- plesty.lib.ui.qt.shell._repolish(widget: PySide6.QtWidgets.QWidget) None
Re-apply the stylesheet after a dynamic property changed.
- Parameters:
widget (PySide6.QtWidgets.QWidget)
- Return type:
None
- class plesty.lib.ui.qt.shell.PanelTitleBar(dock: DockPanel, title: str, closable: bool = True)
Bases:
PySide6.QtWidgets.QWidgetTitle bar of a sub-window: state dot, title, live status, controls.
Replaces Qt’s default dock title bar so a panel can show what it is doing without stealing plot area — the same window-chrome language as the plesty.net hero card. Mouse presses are left unhandled on purpose, so the dock widget beneath still starts a drag: this bar is the drag handle that pulls a panel out of the home window.
Build the bar for dock.
- Parameters:
dock (DockPanel) – The sub-window this bar belongs to.
title (str) – Text shown on the left.
closable (bool) – Show the close button.
- _dock
- dot
- label
- status
- _button(glyph: str, tip: str, handler: Any) PySide6.QtWidgets.QToolButton
Create one title-bar button.
- Parameters:
glyph (str)
tip (str)
handler (Any)
- Return type:
PySide6.QtWidgets.QToolButton
- set_status(text: str, tone: str = 'idle') None
Update the status line and the state dot.
- Parameters:
text (str) – Status text shown at the right of the bar.
tone (str) – State name understood by the theme (
"running","idle","error","warning").
- Return type:
None
- set_floating(floating: bool) None
Mark the bar as belonging to a floating window.
- Parameters:
floating (bool) – Whether the sub-window is currently floating.
- Return type:
None
- mouseDoubleClickEvent(event: Any) None
Toggle floating on a double click, as a title bar conventionally does.
- Parameters:
event (Any) – The Qt mouse event.
- Return type:
None
- class plesty.lib.ui.qt.shell.DockPanel(panel: plesty.lib.ui.panel.Panel, shell: Shell)
Bases:
PySide6.QtWidgets.QDockWidgetOne sub-window of the shell, wrapping a
Panel.Movable, floatable, and (unless the panel says otherwise) closable — the three features that let an operator rearrange the window at will.
Wrap panel into a sub-window of shell.
- Parameters:
panel (plesty.lib.ui.panel.Panel) – The panel to host.
shell (Shell) – The home window.
- panel
- title_bar
- toggle_floating() None
Pull the panel out of the home window, or drop it back in.
- Return type:
None
- refresh() None
Tick the panel and mirror its status into the title bar.
- Return type:
None
- class plesty.lib.ui.qt.shell.Shell(title: str = 'PLESTY', *, theme: plesty.lib.ui.theme.Theme | None = None, interval_ms: int = 500, layout_file: str | pathlib.Path | None = None, remember_layout: bool = True, parent: PySide6.QtWidgets.QWidget | None = None)
Bases:
PySide6.QtWidgets.QMainWindowHome window hosting every panel as a rearrangeable sub-window.
Create the home window.
- Parameters:
title (str) – Window title, also the key of the saved layout.
theme (Optional[plesty.lib.ui.theme.Theme]) – Palette and stylesheet;
Noneloads the packaged PLESTY theme.interval_ms (int) – Refresh interval — how often every panel is ticked. 500 ms keeps a live spectrum fluent without loading the machine that is also running the measurement.
layout_file (Optional[str | pathlib.Path]) – Where to store the arrangement;
Noneuses~/.plesty/ui/<title>.json.remember_layout (bool) – Restore the stored arrangement on open and save it on close.
parent (Optional[PySide6.QtWidgets.QWidget]) – Parent widget.
- theme
- recorder: plesty.lib.ui.qt.recorder.Recorder | None = None
- last_recording: pathlib.Path | None = None
- remember_layout = True
- layout_file
- _timer
- add(panel: plesty.lib.ui.panel.Panel, *, area: str | None = None, tabify_with: str | None = None, split_with: str | None = None) DockPanel
Add a panel as a sub-window.
A panel joining an area that already holds one is split against the last panel there rather than dropped into the area as a whole. Only a split puts a real handle between two panels: docks that merely share an area — or worse, sit in different areas — cannot be resized against each other, which is how a panel ends up as an unadjustable strip.
- Parameters:
panel (plesty.lib.ui.panel.Panel) – The panel to host.
area (Optional[str]) – Docking area override; defaults to
panel.area.tabify_with (Optional[str]) – Name of an already-added panel to tab this one with, instead of giving it its own space.
split_with (Optional[str]) – Name of the panel to split against; defaults to the last one added to the same area.
- Returns:
The created sub-window.
- Raises:
ValueError – If the panel name is already taken, or the panel named in tabify_with / split_with is unknown.
- Return type:
- _named(name: str, action: str) DockPanel
Return an already-added sub-window by panel name.
- Raises:
ValueError – If no panel of that name was added.
- Parameters:
name (str)
action (str)
- Return type:
- _last_in_area(area: str) DockPanel | None
Return the last docked sub-window of area, if it has one.
- Parameters:
area (str)
- Return type:
Optional[DockPanel]
- apply_weights() None
Size the panels of each area in proportion to their panel weights.
Qt distributes leftover space evenly, which leaves a status strip as tall as a spectrum. Weights say what each panel is worth: a plot 3, a readout 1.
- Return type:
None
- remove(name: str) None
Remove a panel and release what it holds.
- Parameters:
name (str) – Name of the panel to remove; unknown names are ignored.
- Return type:
None
- start() None
Show the window, restore the layout, and start refreshing panels.
A stored arrangement wins over the panels’ weights — it is what the operator built last time.
- Return type:
None
- stop() None
Stop refreshing panels.
- Return type:
None
- set_status(text: str, state: str = 'idle') None
Set the shell-wide status line.
- Parameters:
text (str) – Message shown in the status bar.
state (str) – State name coloring the indicator (
"running","idle","error","warning").
- Return type:
None
- _tick() None
Refresh every panel; a failing panel never stops the others.
- Return type:
None
- start_recording(path: str | pathlib.Path, *, fps: int = 10, every: int = 1) plesty.lib.ui.qt.recorder.Recorder
Capture the window after every refresh until
stop_recording().Recording belongs to the window rather than to a view, so whatever is docked is captured — including a panel added or floated halfway through a run.
- Parameters:
path (str | pathlib.Path) – Destination file; the suffix is corrected to what the available encoder can write (MP4, else animated GIF).
fps (int) – Frame rate of the encoded video.
every (int) – Capture one frame per every refreshes.
- Returns:
The recorder, already active.
- Return type:
- stop_recording() pathlib.Path | None
Encode what was captured and stop recording.
- Returns:
The written file, or
Noneif nothing was being recorded.- Return type:
Optional[pathlib.Path]
- _toggle_recording() None
Menu handler: start a recording beside the layout, or stop one.
- Return type:
None
- save_layout(path: str | pathlib.Path | None = None) pathlib.Path
Store the current arrangement.
- Parameters:
path (Optional[str | pathlib.Path]) – Destination file;
Noneuseslayout_file.- Returns:
The path written.
- Return type:
pathlib.Path
- restore_layout(path: str | pathlib.Path | None = None) bool
Restore a stored arrangement, if one exists and still fits.
Panels that were not added this time are simply absent from the restored layout; new ones keep the placement they were added with.
- Parameters:
path (Optional[str | pathlib.Path]) – Layout file;
Noneuseslayout_file.- Returns:
Whether a layout was restored.
- Return type:
bool
- reset_layout() None
Return every panel to the area it was added with, undocked from tabs.
- Return type:
None
- _build_chrome() None
Create the menus and the status bar.
- Return type:
None
- closeEvent(event: Any) None
Save the arrangement and release the panels before closing.
- Parameters:
event (Any) – The Qt close event.
- Return type:
None