plesty.server.view.window
The console’s main window: menu bar, device table, detail pane.
Layout (designed for a bench, not docked):
┌ Bench Device View Help ──────────────────────────────────────────┐
│ ┌ Devices ─────────────────────────────────────────────────────────┐ │
│ │ NAME SOURCE STATE PORT PID STARTED │ │
│ │ pm100d plesty-pm100d==0.2.1 running 5551 4242 10:21:03 │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ ┌ pm100d ──────────────────── [Log] [Jobs] [Reports] ──────────────┐ │
│ │ === plesty-server start … :: python -m plesty.pm100d … │ │
│ │ [SERVER] Running at 127.0.0.1:5551 │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ ~/.plesty/server · fleet.yaml · 2 devices · refreshed 10:21:05 │
└────────────────────────────────────────────────────────────────────┘
The window owns a Bench and a Worker; every menu action
calls one presenter method on the worker and refreshes when it returns.
Attributes
Classes
The console window. |
Functions
|
A titled card with optional buttons: the console's layout primitive. |
|
A card-header button wired to slot. |
|
A path with the home directory abbreviated to |
|
|
|
The palette colour for a state, looked up from the theme on the window. |
Module Contents
- plesty.server.view.window.COLUMNS = ('Fleet', 'Name', 'Source', 'State', 'Port', 'PID', 'Started')
- plesty.server.view.window.CHECK_COLUMN = 0
- plesty.server.view.window.NAME_COLUMN = 1
- plesty.server.view.window.REFRESH_MS = 3000
- plesty.server.view.window.NOTICE_MS = 20000
- class plesty.server.view.window.MainWindow(bench: plesty.server.presenter.Bench, title: str = 'PLESTY bench', version: str = '')
Bases:
PySide6.QtWidgets.QMainWindowThe console window.
Build the window around bench.
- Parameters:
bench (plesty.server.presenter.Bench) – The presenter.
title (str) – Window title.
version (str) – Shown in the About box.
- notice
- bench
- version = ''
- worker
- _views: list[plesty.server.presenter.DeviceView] = []
- _starting: set[str]
- _timer
- Return type:
None
- _add(menu: PySide6.QtWidgets.QMenu, text: str, slot: collections.abc.Callable[[], Any], shortcut: Any = None) PySide6.QtGui.QAction
- Parameters:
menu (PySide6.QtWidgets.QMenu)
text (str)
slot (collections.abc.Callable[[], Any])
shortcut (Any)
- Return type:
PySide6.QtGui.QAction
- _build_body() None
- Return type:
None
- property selected: str | None
Name of the selected device, or
None.- Return type:
str | None
- select(name: str) None
Select the row of name (no-op when absent).
- Parameters:
name (str)
- Return type:
None
- refresh() None
Re-read the devices on the worker and repaint when they arrive.
- Return type:
None
- _show_devices(views: list[plesty.server.presenter.DeviceView]) None
- Parameters:
views (list[plesty.server.presenter.DeviceView])
- Return type:
None
- _selection_changed() None
- Return type:
None
- _update_buttons() None
Enable the device buttons for the selected row and its state.
- Return type:
None
- _refresh_detail() None
- Return type:
None
- _show_log(text: str) None
- Parameters:
text (str)
- Return type:
None
- _show_jobs(jobs: list[plesty.server.model.Job]) None
- Parameters:
jobs (list[plesty.server.model.Job])
- Return type:
None
- _show_reports(reports: list[Any]) None
- Parameters:
reports (list[Any])
- Return type:
None
- _note(line: str) None
Show a progress line on its own row, and keep it.
Its own row, because a failure is standing information the operator has to act on and progress is not: neither may hide the other, which is also why this is not
QStatusBar.showMessage— that hides every non-permanent widget, the standing failure included.It clears itself after
NOTICE_MS, because “installing …” an hour later is a lie about what the bench is doing. Nothing is lost — View ▸ Messages… has every line of the session.- Parameters:
line (str)
- Return type:
None
- clear_notice() None
Drop the progress line (the timer, and any action that finishes).
- Return type:
None
- property notice_text: str
The progress line currently shown (empty when none).
- Return type:
str
- show_messages() None
View → Messages…: every progress line this session, newest last.
- Return type:
None
- _show_message(text: str, tone: str) None
- Parameters:
text (str)
tone (str)
- Return type:
None
- show_error(message: str) None
Report a failure in the window, where it costs the operator nothing to read.
Not a modal. What fails here fails asynchronously — an install takes minutes and the operator is often elsewhere — and a modal blocks the Qt event loop: the device table stops refreshing, an open job log stops tailing, and the console is frozen until somebody clicks it away. The message stays until it is dismissed or another replaces it.
- Parameters:
message (str)
- Return type:
None
- clear_error() None
Hide the standing message (the Dismiss button, and any action that succeeds).
- Return type:
None
- property error_text: str
What the window is currently reporting as failed (empty when nothing).
- Return type:
str
- _call(action: collections.abc.Callable[[], Any], then: collections.abc.Callable[[Any], None] | None = None) None
Run a presenter call on the worker; refresh afterwards, report on error.
- Parameters:
action (collections.abc.Callable[[], Any])
then (collections.abc.Callable[[Any], None] | None)
- Return type:
None
- _require() str | None
- Return type:
str | None
- _item_changed(item: PySide6.QtWidgets.QTableWidgetItem) None
A check box toggled: include/exclude the device from the working fleet.
- Parameters:
item (PySide6.QtWidgets.QTableWidgetItem)
- Return type:
None
- _fleets_dir() pathlib.Path
Where the fleet file dialogs start:
<home>/fleets/(created on demand).- Return type:
pathlib.Path
- new_fleet(path: str | None = None) None
File → New fleet…: an empty fleet file, made current (devices are added to it).
- Parameters:
path (str | None)
- Return type:
None
- open_fleet(path: str | None = None) None
File → Open fleet…: replace the declarations with another fleet file.
- Parameters:
path (str | None)
- Return type:
None
- save_fleet_as(path: str | None = None) None
File → Save working fleet as…: the checked devices to a new fleet file.
- Parameters:
path (str | None)
- Return type:
None
- _fleet_changed() None
- Return type:
None
- edit_device_config() None
Edit → Device config…: declaration + .env of the highlighted device.
The catalogue is fetched on the worker first, so the module’s repository URL and latest tag are in the drop-downs when the operator switches a release declaration to a repository one.
- Return type:
None
- edit_fleet_file() None
Edit → Fleet file…: the YAML of the whole fleet.
- Return type:
None
- open_catalogue() None
Catalogue → Search & install…: fetch the hub catalogue, install a module.
Only the module: the fleet is not touched here. Declaring an instance of it is Edit ▸ Add device…, which offers what the bench holds.
- Return type:
None
- declare_device() None
Edit → Add device…: declare an instance of an installed module.
With nothing installed the user is sent to the catalogue instead.
- Return type:
None
- edit_device() None
Edit the declaration only (used by the context menu).
- Return type:
None
- remove_device() None
Edit → Remove from fleet (also the Remove button).
- Return type:
None
- start_device() None
Device → Start (one start at a time per device).
- Return type:
None
- stop_device() None
Device → Stop.
- Return type:
None
- restart_device() None
Device → Restart.
- Return type:
None
- install_device() None
Device → Install: starts the job and opens its dialog.
- Return type:
None
- update_device() None
Device → Update: starts the job and opens its dialog.
- Return type:
None
- uninstall_device() None
Device → Uninstall.
- Return type:
None
- field_test_device() None
Device → Field test…: configure, start the job, open its dialog.
- Return type:
None
- fleet_up() None
Device → Fleet up (the working fleet).
- Return type:
None
- fleet_down() None
Device → Fleet down (the working fleet).
- Return type:
None
- show_jobs() None
View → Jobs…: the Jobs tab of the detail pane.
- Return type:
None
- _open_job(job: plesty.server.model.Job) None
- Parameters:
job (plesty.server.model.Job)
- Return type:
None
- _open_job_row(item: PySide6.QtWidgets.QTableWidgetItem) None
- Parameters:
item (PySide6.QtWidgets.QTableWidgetItem)
- Return type:
None
- Parameters:
pos (Any)
- Return type:
None
- closeEvent(event: Any) None
Closing the console closes what it manages: servers and running jobs.
Asks first when something is running — an accidental close must not take a bench down — then stops everything synchronously so nothing is left unmanaged behind a window that is gone.
- Parameters:
event (Any)
- Return type:
None
- plesty.server.view.window._card(title: str | PySide6.QtWidgets.QLabel, body: PySide6.QtWidgets.QWidget, buttons: list[PySide6.QtWidgets.QWidget] | None = None, own_row: bool = False) PySide6.QtWidgets.QWidget
A titled card with optional buttons: the console’s layout primitive.
- Parameters:
title (str | PySide6.QtWidgets.QLabel) – Card title (a label is reused as-is).
body (PySide6.QtWidgets.QWidget) – The card’s content.
buttons (list[PySide6.QtWidgets.QWidget] | None) – Buttons shown on the title line (few) or, with own_row, on a bar of their own between the title and the body (many).
own_row (bool) – Put the buttons on their own row.
- Return type:
PySide6.QtWidgets.QWidget
- plesty.server.view.window._button(text: str, slot: collections.abc.Callable[[], Any], tooltip: str = '', primary: bool = False, danger: bool = False) PySide6.QtWidgets.QPushButton
A card-header button wired to slot.
- Parameters:
text (str)
slot (collections.abc.Callable[[], Any])
tooltip (str)
primary (bool)
danger (bool)
- Return type:
PySide6.QtWidgets.QPushButton
- plesty.server.view.window._short(path: Any) str
A path with the home directory abbreviated to
~.- Parameters:
path (Any)
- Return type:
str
- plesty.server.view.window._clock(stamp: str | None) str
HH:MM:SSof an ISO timestamp (local time), or"".- Parameters:
stamp (str | None)
- Return type:
str
- plesty.server.view.window._tone_brush(widget: PySide6.QtWidgets.QWidget, state: str) Any
The palette colour for a state, looked up from the theme on the window.
- Parameters:
widget (PySide6.QtWidgets.QWidget)
state (str)
- Return type:
Any