spacr.qt.widgets.eliding

Qt labels and buttons that elide text without losing the full value.

The widgets render an ellipsis when space is limited and expose the complete text in a tooltip. Stable size hints prevent layouts from oscillating between full and shortened text.

PROGRESS LINE. ProgressLine is a slim progress bar whose numbers sit beside it, where nothing can cut them.

WHY. The theme draws every QProgressBar as an 8 px track (height: 8px; max-height: 8px in spacr.qt.theme). A bar that also paints its own text – “step 2 of 3”, “45%”, “312 MB / 690 MB (45%)” – draws a 13 px caption into those 8 px, so only the top half of each glyph reaches the screen, and at 50 % GUI scale the track is 4 px and almost nothing does. A caption such as “step 1 of 3” or “10%” is cut off.

THE DESIGN is “thin bar + label”:

[████████░░░░░░░░░░░░] step 2 of 3 · 45% Downloading torch… 312 MB of 690 MB · 4.2 MB/s · 1 min 30 s left

  • the bar paints no text at all and stays the slim track the theme draws;

  • the COUNT beside it (the step and the percentage, the numbers a person is watching) is a plain label that is never elided – its horizontal size policy is Minimum, so a layout cannot give it less than its text needs;

  • an optional DETAIL line below carries the part that changes and can be long (a file name, a speed, a time left); that part elides, and ProgressLine.displayed_text() reports what is really painted.

No size here is computed from font metrics and then handed to a size setter, so the GUI-scale layer (spacr.qt.gui_scale) scales each size once: the label follows the scaled font, the spacing follows the scaled layout.

The widget answers the parts of QProgressBar’s API the call sites use (setRange, setValue, setFormat with %p/%v/%m, setTextVisible, format, value …), so swapping one in for a bar changes one line at each site.

Classes

ElidingLabel

A QLabel that elides rather than clips.

ElidingPushButton

A QPushButton whose label elides rather than clips.

ProgressLine

A thin bar with its count beside it and an optional detail line below.

Module Contents

class spacr.qt.widgets.eliding.ElidingLabel(text: str = '', parent=None, mode: PySide6.QtCore.Qt.TextElideMode = Qt.ElideRight)[source]

Bases: PySide6.QtWidgets.QLabel

A QLabel that elides rather than clips.

Parameters:
  • text – the full text to display.

  • parent – optional parent widget.

  • mode – where the ellipsis goes; defaults to Qt.ElideRight.

Create a label that shortens its text rather than forcing a width.

Parameters:
  • text – the full text; kept, so widening restores it.

  • parent – parent widget, or None.

  • mode – where the ellipsis goes.

available_text_width() → int[source]

Px currently available to draw text in, margins removed.

full_text() → str[source]

The complete, un-elided text as handed to setText().

is_elided() → bool[source]

True when the displayed text is a shortened copy.

minimumSizeHint() → PySide6.QtCore.QSize[source]

Allow shrinking to a few characters so the parent can cap us.

required_width() → int[source]

Width in px at which the full text renders without eliding.

resizeEvent(event) → None[source]

Re-elide whenever the layout hands us a different width.

Parameters:

event – the resize event, passed to the base class; the text is then re-fitted to the label’s new width.

setText(text: str) → None[source]

Set the full text, then render as much of it as fits.

Parameters:

text – the full label text; None is treated as "". When it has to be elided, the full text becomes the tooltip.

sizeHint() → PySide6.QtCore.QSize[source]

Hint the width of the full text so the layout can grant it.

class spacr.qt.widgets.eliding.ElidingPushButton(text: str = '', parent=None, mode: PySide6.QtCore.Qt.TextElideMode = Qt.ElideRight)[source]

Bases: PySide6.QtWidgets.QPushButton

A QPushButton whose label elides rather than clips.

Used for the sidebar navigation items, where the column has a fixed width and the app names keep getting longer.

Parameters:
  • text – the full button text.

  • parent – optional parent widget.

  • mode – where the ellipsis goes; defaults to Qt.ElideRight.

Create a button that shortens its label rather than forcing a width.

The horizontal policy is loosened deliberately: without it the layout treats the size hint as a hard minimum and squeezes the whole sidebar instead of shortening one label.

Parameters:
  • text – the full text; kept, so widening restores it.

  • parent – parent widget, or None.

  • mode – where the ellipsis goes.

available_text_width() → int[source]

Px left for the label once the icon and style padding are paid for.

Derived from the button’s own size hint (hint minus the advance of the text it currently shows == everything that is not text), so it follows the active style instead of assuming padding values.

full_text() → str[source]

The complete, un-elided text as handed to setText().

is_elided() → bool[source]

True when the displayed text is a shortened copy.

minimumSizeHint() → PySide6.QtCore.QSize[source]

Allow shrinking to a handful of characters plus the icon.

resizeEvent(event) → None[source]

Re-elide whenever the layout hands us a different width.

Parameters:

event – the resize event, passed to the base class; the label is then re-fitted to the button’s new width.

setText(text: str) → None[source]

Set the full text, then render as much of it as fits.

Parameters:

text – the full button label; None is treated as "".

sizeHint() → PySide6.QtCore.QSize[source]

Hint the width the full text needs, elided or not.

QPushButton.sizeHint measures the text currently set, which after eliding is shorter than the real name; adding back the difference keeps the hint stable across elide/unelide.

class spacr.qt.widgets.eliding.ProgressLine(parent=None, *, detail: bool = True, count_below: bool = False)[source]

Bases: PySide6.QtWidgets.QWidget

A thin bar with its count beside it and an optional detail line below.

Parameters:
  • parent – parent widget, or None.

  • detail – whether to build the eliding detail line under the bar.

  • count_below – put the count on its own line under the bar, at the left, instead of beside it – for a side panel whose content can be wider than the pane, where the right end of a row is scrolled away.

Build the bar, the count label and, if asked, the detail line.

Parameters:
  • parent – parent widget, or None.

  • detail – build the detail line under the bar.

  • count_below – the count under the bar instead of beside it.

count_text() → str[source]

The count as it is written beside the bar (never elided).

detail_text() → str[source]

The full detail line, before any eliding.

displayed_text() → str[source]

What is really painted: the count, then the detail as elided.

Hidden parts are left out, so a test compares against the screen.

format() → str[source]

The count template last handed to setFormat().

isTextVisible() → bool[source]

Whether the count beside the bar is shown.

maximum() → int[source]

The value at a full bar.

minimum() → int[source]

The value at an empty bar.

percent()[source]

The whole percentage the bar shows, or None while busy.

reset() → None[source]

Empty the bar the way QProgressBar.reset does.

setFormat(text: str) → None[source]

Set the count template, with QProgressBar’s %p %v %m.

A template with no %p gets the percentage appended after a separator whenever the bar has a range, so the number is never lost.

Parameters:

text – the template, e.g. "step 2 of 3" or "%v / %m jobs".

setMaximum(maximum: int) → None[source]

Set the value at a full bar.

Parameters:

maximum – the new maximum.

setMinimum(minimum: int) → None[source]

Set the value at an empty bar.

Parameters:

minimum – the new minimum.

setRange(minimum: int, maximum: int) → None[source]

Set the bar’s range; (0, 0) is the busy state with no number.

Parameters:
  • minimum – the value at an empty bar.

  • maximum – the value at a full bar.

setTextVisible(visible: bool) → None[source]

Show or hide the count beside the bar; the bar never paints text.

Parameters:

visible – whether the count label is shown.

setValue(value: int) → None[source]

Move the bar and the numbers beside it.

Parameters:

value – the new value, clamped by the bar to its range.

set_detail(text: str) → None[source]

Set the line under the bar; it elides when the window is narrow.

Parameters:

text – the changing part – a file name, a speed, a time left.

text() → str[source]

The count as it is written beside the bar.

value() → int[source]

The bar’s current value.