spacr.qt.live_zoom¶
Hold Z and turn the wheel to resize the interface’s text, live.
THE LIVE ZOOM GESTURE, and the measurement that shaped it.
The request came with a condition – “only if possible to do fast without lag” – so the first question was what a notch costs. On one 1440x900 MainWindow with 847 widgets:
stylesheet() rebuild 1.4 ms app.setStyleSheet(…) + repolish 587.5 ms <- Preferences repolish the visible screen only 107 ms QApplication.setFont(…) 14 ms
Only the last one is live, and it moves nothing: the application sheet
carries 49 hardcoded font-size: <N>px declarations, and a QSS font-size
beats the inherited application font.
THE ESCAPE THE INSTRUCTION PROPOSED DOES NOT EXIST. Part 2 of 378 assumed
the 49 declarations could be rewritten in em or % so that one
setFont moved everything. Qt does not implement either for
font-size: QCss accepts only pt, px and the CSS size
keywords, and silently drops any other unit, so font-size: 2em leaves
the widget at the inherited size. Measured on this PySide6, and
pinned by test_qt_still_has_no_relative_font_size, which fails the day
Qt gains the unit and makes the simpler design available.
WHAT IS LIVE INSTEAD. An explicit QWidget.setFont does beat the
application sheet’s font-size – it is the same escape hatch that lets a
per-widget sheet win – and it costs one font assignment and one relayout
rather than a global unpolish/repolish. So a notch snapshots each visible
widget’s font once, then re-scales every widget from that snapshot by the
ratio the wheel has travelled. The role hierarchy survives because each
widget is scaled from its own baseline: a 22 px title and a 13 px caption
stay in proportion without this module knowing which is which.
WHAT IS NOT LIVE, AND WHY THAT WAS ACCEPTED. Every size the font scale pins
from Python – row heights, column widths, icon sizes, tile geometry, all of
spacr.qt.preferences.scaled_px() – moves only when the stylesheet is
rebuilt, and that is the 587 ms number. The choice made:
“Text live, spacing on release.” Text follows the wheel; the spacing around
it catches up in one step when the wheel stops or Z comes up. It is a
deliberate compromise, not an oversight, and it is why the settle exists.
AND THE ICONS DID NOT MOVE AT ALL, which was NOT part of that compromise.
The spacing caught up at the settle; the icons never caught up, because an
icon size is neither a stylesheet value nor a scaled_px call that
anything re-ran – it is a widget PROPERTY written once when the widget was
built, so a scale that grew every caption left every glyph beside those
captions exactly where it was. The settle now re-derives them, through
spacr.qt.preferences._rescale_icon_sizes(), inside the same
apply_preferences_to_app step that rebuilds the sheet: 5.5 ms for the
2,122 widgets of a window with two modules open, against the 395-877 ms
that step costs when the scale really changes. Nothing was added to the
live half.
Classes¶
Ctrl + wheel over a module screen's right-hand column sizes its text. |
|
Application-wide filter that turns Z + wheel into a live font scale. |
Functions¶
|
Every |
|
Install the Ctrl + wheel column gesture on the application, once. |
|
Install the Z + wheel font gesture on a running application. |
|
Let Ctrl + wheel over |
|
The font sizes of |
Module Contents¶
- class spacr.qt.live_zoom.ColumnTextScale(parent: PySide6.QtCore.QObject | None = None)[source]¶
Bases:
PySide6.QtCore.QObjectCtrl + wheel over a module screen’s right-hand column sizes its text.
Holding Ctrl and turning the wheel over any panel in that column makes its text larger or smaller.
ONE SIZE FOR EVERY COLUMN, persisted in
spacr.qt.preferences.get_runtime_text_scale(). It multiplies the size the rest of the interface has, so the whole-GUI scale (471) and the Z gesture (378) still move the column with everything else.A STYLE SHEET ON THE COLUMN, NOT
setFont. The Z gesture’ssetFontis undone by the next repolish (measured: a label set to 20 px is back at its sheet’s 13 px afterunpolish/polish), and the column’s widgets repolish every time a card folds or a run starts.scaled_font_sheet()re-declares the inherited sizes on the column itself, which only its descendants see. A widget that sizes its own text from Python and so outranks any sheet – the console’s entries – takes the size through anapply_column_text_scale(scale)method instead.AN APPLICATION FILTER, because the console and every scroll area in the column accept the wheel before a parent could see it. It yields to:
the Z gesture while Z is held – Z + wheel is 378’s;
any widget between the pointer and the column that handles the wheel in Python – the plaque and live-preview canvases zoom on Ctrl + wheel and a figure canvas has its own scroll – which keeps the gesture to the text panels;
everything outside a registered column.
Ctrl+0 with the pointer over a column whose text is not at 100 % puts it back; at 100 % the key is left to Go home, which it otherwise is.
Create the filter with the stored size and no columns yet.
- eventFilter(watched, event)[source]¶
Take Ctrl + wheel and Ctrl+0 over a column; restyle on a change.
- Parameters:
watched – the object the event is for.
event – the event.
- Returns:
True when the event was the gesture’s.
- register(root) None[source]¶
Make
roota column whose text Ctrl + wheel sizes.- Parameters:
root – the container; everything inside it follows.
- restyle(root) bool[source]¶
Re-declare
root’s inherited sizes at the present scale.Idempotent: nothing is set unless the scale or an inherited sheet changed since the last time, which is what lets this run on every
StyleChangethe column receives – setting the column’s own sheet sends it one. A column never scaled wears no sheet of its own; one that was scaled keeps declaring its sizes at 100 %, because taking a font rule away does not give Qt’s widgets their old font back (measured: 23 of the Measure column’s 58 widgets kept the larger size when the sheet was emptied).- Parameters:
root – a registered column.
- Returns:
whether the column’s sheet was replaced.
- class spacr.qt.live_zoom.LiveZoomFilter(parent: PySide6.QtCore.QObject | None = None)[source]¶
Bases:
PySide6.QtCore.QObjectApplication-wide filter that turns Z + wheel into a live font scale.
Installed on the QApplication because the gesture has to work on every screen – a per-screen handler works in some places and not others, which is the complaint that produced 315’s warning about application filters. That warning is about COST, so the body is two integer comparisons for an event it does not want, and the wheel branch is not even reached unless Z is down. Measured at 1.2 us per uninteresting event on this machine, which is the Python call itself rather than anything this does inside it.
Create the filter that scales the interface while the key is held.
The starting scale and the widgets’ original fonts are recorded so the gesture can be undone exactly, including which of them carried a font of their own rather than inheriting one – restoring an inherited font as an explicit one would pin it against every later theme change.
- Parameters:
parent – parent object, or
None.
- eventFilter(watched, event)[source]¶
Watch the widgets this filter is installed on.
- Parameters:
watched – the object the event is for.
event – the event.
- Returns:
True to stop the event going further.
- settle(released: bool = True) None[source]¶
End the gesture: persist the scale and let the spacing catch up.
THE EXPENSIVE HALF, ON PURPOSE. Everything
scaled_px()pins is rebuilt here, in one 587 ms step, rather than twenty times a second while the wheel turns – which is the compromise chosen over a gesture that stutters. Called when the wheel has been still for_SETTLE_MS, when Z comes up, and when the window loses focus with Z still down.THE ICONS CATCH UP HERE TOO, and here only. They ride inside
apply_preferences_to_apprather than being resized per notch, because the condition on this gesture was that it be fast without lag and the live half is the half that has to answer for it. The sweep is 5.5 ms on 2,122 widgets, so it COULD have gone in the live half – it is here because the icons would then have grown inside spacing that had not, which is the mismatch that made the icons look wrong in the first place.The QSettings write happens here too, for the same reason: twenty writes a second to a settings file is not free.
- Parameters:
released – whether Z is now up. False when the wheel merely went quiet: the user is still holding the key and may keep scrolling, and disarming under them would make the second half of one gesture scroll the list. The next notch simply starts a fresh gesture from the scale this one just saved.
- spacr.qt.live_zoom.font_size_rules(sheet: str) list[source]¶
Every
(selector, size, unit)insheetthat sets a font size.- Parameters:
sheet – Qt style sheet text.
- spacr.qt.live_zoom.install_column_text_scale(app=None) ColumnTextScale | None[source]¶
Install the Ctrl + wheel column gesture on the application, once.
- Parameters:
app – optional QApplication; falls back to the running instance.
- Returns:
the filter, or None when there is no application to hold it.
- spacr.qt.live_zoom.install_live_zoom(app=None) LiveZoomFilter | None[source]¶
Install the Z + wheel font gesture on a running application.
Idempotent: the filter is retained on the application object, so a second call returns the one already installed rather than stacking a second filter onto every event in the process.
- Parameters:
app – optional QApplication; falls back to the running instance.
- Returns:
the filter, or None when there is no application to hold it.
- spacr.qt.live_zoom.register_text_column(root) ColumnTextScale | None[source]¶
Let Ctrl + wheel over
rootsize the text inside it.- Parameters:
root – a module screen’s right-hand column.
- Returns:
the filter, or None without an application.
- spacr.qt.live_zoom.scaled_font_sheet(sheet: str, ratio: float) str[source]¶
The font sizes of
sheet, and nothing else, multiplied byratio.Set on a container, this re-declares every size the window’s sheet gives the widgets inside it: a container’s sheet beats an ancestor’s whatever the specificity, so the whole hierarchy of sizes – a 15 px card title over 12 px captions – moves together and stays in proportion, and widgets built later inside the container follow without being visited.
- Parameters:
sheet – the sheet the container inherits.
ratio – the multiplier; 1.0 gives the same sizes back.