Improve styling and logging for UI font-size zoom
Refine zoom methods in `MainWindow` and font helpers in `_style` to return `px_size` up the call chain and log detailed zoom state on each change. Deats, - make `_set_qfont_px_size()` return `self.px_size`. - make `configure_to_dpi()` and `_config_fonts_to_screen()` return the new `px_size` up through the call chain. - add `font_size` to `log.info()` in `zoom_in()`, `zoom_out()`, and `reset_zoom()` alongside `zoom_step` and `zoom_level(%)`. - reformat `has_ctrl`/`_has_shift` bitwise checks and key-match tuples to multiline style. - comment out `Shift` modifier requirement for zoom hotkeys (now `Ctrl`-only). - comment out unused `mn_dpi` and `dpi` locals. Also, - convert all single-line docstrings to `'''` multiline style across zoom and font methods. - rewrap `configure_to_dpi()` docstring to 67 chars. - move `from . import _style` to module-level import in `_window.py`. - drop unused `screen` binding in `boundingRect()`. (this commit msg was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-codedpi-font-auto-calc_goodboy_test
parent
88a9ae4144
commit
9b5f92f818
|
|
@ -79,9 +79,13 @@ class DpiAwareFont:
|
||||||
self._font_inches: float = None
|
self._font_inches: float = None
|
||||||
self._screen = None
|
self._screen = None
|
||||||
|
|
||||||
def _set_qfont_px_size(self, px_size: int) -> None:
|
def _set_qfont_px_size(
|
||||||
|
self,
|
||||||
|
px_size: int,
|
||||||
|
) -> int:
|
||||||
self._qfont.setPixelSize(int(px_size))
|
self._qfont.setPixelSize(int(px_size))
|
||||||
self._qfm = QtGui.QFontMetrics(self._qfont)
|
self._qfm = QtGui.QFontMetrics(self._qfont)
|
||||||
|
return self.px_size
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def screen(self) -> QtGui.QScreen:
|
def screen(self) -> QtGui.QScreen:
|
||||||
|
|
@ -128,17 +132,18 @@ class DpiAwareFont:
|
||||||
self,
|
self,
|
||||||
screen: QtGui.QScreen | None = None,
|
screen: QtGui.QScreen | None = None,
|
||||||
zoom_level: float = 1.0,
|
zoom_level: float = 1.0,
|
||||||
):
|
) -> int:
|
||||||
'''
|
'''
|
||||||
Set an appropriately sized font size depending on the screen DPI.
|
Set an appropriately sized font size depending on the screen DPI
|
||||||
|
or scale the size according to `zoom_level`.
|
||||||
|
|
||||||
If we end up needing to generalize this more here there are resources
|
If we end up needing to generalize this more here there are
|
||||||
listed in the script in ``snippets/qt_screen_info.py``.
|
resources listed in the script in
|
||||||
|
``snippets/qt_screen_info.py``.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
if self._font_size is not None:
|
if self._font_size is not None:
|
||||||
self._set_qfont_px_size(self._font_size * zoom_level)
|
return self._set_qfont_px_size(self._font_size * zoom_level)
|
||||||
return
|
|
||||||
|
|
||||||
# NOTE: if no font size set either in the [ui] section of the
|
# NOTE: if no font size set either in the [ui] section of the
|
||||||
# config or not yet computed from our magic scaling calcs,
|
# config or not yet computed from our magic scaling calcs,
|
||||||
|
|
@ -157,7 +162,7 @@ class DpiAwareFont:
|
||||||
ldpi = pdpi
|
ldpi = pdpi
|
||||||
|
|
||||||
mx_dpi = max(pdpi, ldpi)
|
mx_dpi = max(pdpi, ldpi)
|
||||||
mn_dpi = min(pdpi, ldpi)
|
# mn_dpi = min(pdpi, ldpi)
|
||||||
scale = round(ldpi/pdpi, ndigits=2)
|
scale = round(ldpi/pdpi, ndigits=2)
|
||||||
|
|
||||||
if mx_dpi <= 97: # for low dpi use larger font sizes
|
if mx_dpi <= 97: # for low dpi use larger font sizes
|
||||||
|
|
@ -166,7 +171,7 @@ class DpiAwareFont:
|
||||||
else: # hidpi use smaller font sizes
|
else: # hidpi use smaller font sizes
|
||||||
inches = _font_sizes['hi'][self._font_size_calc_key]
|
inches = _font_sizes['hi'][self._font_size_calc_key]
|
||||||
|
|
||||||
dpi = mn_dpi
|
# dpi = mn_dpi
|
||||||
|
|
||||||
mult = 1.0
|
mult = 1.0
|
||||||
|
|
||||||
|
|
@ -213,10 +218,10 @@ class DpiAwareFont:
|
||||||
f"\nOur best guess font size is {font_size}\n"
|
f"\nOur best guess font size is {font_size}\n"
|
||||||
)
|
)
|
||||||
# apply the size
|
# apply the size
|
||||||
self._set_qfont_px_size(font_size)
|
return self._set_qfont_px_size(font_size)
|
||||||
|
|
||||||
def boundingRect(self, value: str) -> QtCore.QRectF:
|
def boundingRect(self, value: str) -> QtCore.QRectF:
|
||||||
if (screen := self.screen) is None:
|
if self.screen is None:
|
||||||
raise RuntimeError("You must call .configure_to_dpi() first!")
|
raise RuntimeError("You must call .configure_to_dpi() first!")
|
||||||
|
|
||||||
unscaled_br: QtCore.QRectF = self._qfm.boundingRect(value)
|
unscaled_br: QtCore.QRectF = self._qfm.boundingRect(value)
|
||||||
|
|
@ -233,12 +238,22 @@ _font = DpiAwareFont()
|
||||||
_font_small = DpiAwareFont(_font_size_key='small')
|
_font_small = DpiAwareFont(_font_size_key='small')
|
||||||
|
|
||||||
|
|
||||||
def _config_fonts_to_screen(zoom_level: float = 1.0) -> None:
|
def _config_fonts_to_screen(
|
||||||
'configure global DPI aware font sizes'
|
zoom_level: float = 1.0
|
||||||
|
) -> int:
|
||||||
|
'''
|
||||||
|
Configure global DPI aware font size(s).
|
||||||
|
|
||||||
|
If `zoom_level` is provided we apply it to auto-calculated
|
||||||
|
DPI-aware font.
|
||||||
|
|
||||||
|
Return the new `DpiAwareFont.px_size`.
|
||||||
|
|
||||||
|
'''
|
||||||
global _font, _font_small
|
global _font, _font_small
|
||||||
_font.configure_to_dpi(zoom_level=zoom_level)
|
_font.configure_to_dpi(zoom_level=zoom_level)
|
||||||
_font_small.configure_to_dpi(zoom_level=zoom_level)
|
_font_small.configure_to_dpi(zoom_level=zoom_level)
|
||||||
|
return _font.px_size
|
||||||
|
|
||||||
|
|
||||||
def get_fonts() -> tuple[
|
def get_fonts() -> tuple[
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
Qt main window singletons and stuff.
|
Qt main window singletons and stuff.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
|
|
@ -44,7 +43,11 @@ from piker.ui.qt import (
|
||||||
QObject,
|
QObject,
|
||||||
)
|
)
|
||||||
from ..log import get_logger
|
from ..log import get_logger
|
||||||
from ._style import _font_small, hcolor
|
from . import _style
|
||||||
|
from ._style import (
|
||||||
|
_font_small,
|
||||||
|
hcolor,
|
||||||
|
)
|
||||||
from ._widget import GodWidget
|
from ._widget import GodWidget
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -52,7 +55,7 @@ log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class GlobalZoomEventFilter(QObject):
|
class GlobalZoomEventFilter(QObject):
|
||||||
"""
|
'''
|
||||||
Application-level event filter for global UI zoom shortcuts.
|
Application-level event filter for global UI zoom shortcuts.
|
||||||
|
|
||||||
This filter intercepts keyboard events BEFORE they reach widgets,
|
This filter intercepts keyboard events BEFORE they reach widgets,
|
||||||
|
|
@ -64,18 +67,18 @@ class GlobalZoomEventFilter(QObject):
|
||||||
- Ctrl+Shift+Minus: Zoom out
|
- Ctrl+Shift+Minus: Zoom out
|
||||||
- Ctrl+Shift+0: Reset zoom
|
- Ctrl+Shift+0: Reset zoom
|
||||||
|
|
||||||
"""
|
'''
|
||||||
|
|
||||||
def __init__(self, main_window: MainWindow):
|
def __init__(self, main_window: MainWindow):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.main_window = main_window
|
self.main_window = main_window
|
||||||
|
|
||||||
def eventFilter(self, obj: QObject, event: QEvent) -> bool:
|
def eventFilter(self, obj: QObject, event: QEvent) -> bool:
|
||||||
"""
|
'''
|
||||||
Filter keyboard events for global zoom shortcuts.
|
Filter keyboard events for global zoom shortcuts.
|
||||||
|
|
||||||
Returns True to filter out (consume) the event, False to pass through.
|
Returns True to filter out (consume) the event, False to pass through.
|
||||||
"""
|
|
||||||
|
'''
|
||||||
if event.type() == QEvent.Type.KeyPress:
|
if event.type() == QEvent.Type.KeyPress:
|
||||||
key = event.key()
|
key = event.key()
|
||||||
mods = event.modifiers()
|
mods = event.modifiers()
|
||||||
|
|
@ -84,28 +87,49 @@ class GlobalZoomEventFilter(QObject):
|
||||||
mods = mods & ~Qt.KeyboardModifier.KeypadModifier
|
mods = mods & ~Qt.KeyboardModifier.KeypadModifier
|
||||||
|
|
||||||
# Check if we have Ctrl+Shift (both required)
|
# Check if we have Ctrl+Shift (both required)
|
||||||
has_ctrl = bool(mods & Qt.KeyboardModifier.ControlModifier)
|
has_ctrl = bool(
|
||||||
has_shift = bool(mods & Qt.KeyboardModifier.ShiftModifier)
|
mods
|
||||||
|
&
|
||||||
|
Qt.KeyboardModifier.ControlModifier
|
||||||
|
)
|
||||||
|
_has_shift = bool(
|
||||||
|
mods
|
||||||
|
&
|
||||||
|
Qt.KeyboardModifier.ShiftModifier
|
||||||
|
)
|
||||||
|
|
||||||
# Only handle UI zoom if BOTH Ctrl and Shift are pressed
|
# Only handle UI zoom if BOTH Ctrl and Shift are pressed
|
||||||
# For Plus key: user presses Cmd+Shift+Equal (which makes Plus)
|
# For Plus key: user presses Cmd+Shift+Equal (which makes Plus)
|
||||||
# For Minus key: user presses Cmd+Shift+Minus
|
# For Minus key: user presses Cmd+Shift+Minus
|
||||||
if has_ctrl and has_shift:
|
if (
|
||||||
|
has_ctrl
|
||||||
|
# and
|
||||||
|
# has_shift
|
||||||
|
):
|
||||||
# Zoom in: Ctrl+Shift+Plus
|
# Zoom in: Ctrl+Shift+Plus
|
||||||
# Note: Plus key usually comes as Key_Equal with Shift modifier
|
# Note: Plus key usually comes as Key_Equal with Shift modifier
|
||||||
if key in (Qt.Key.Key_Plus, Qt.Key.Key_Equal):
|
if key in (
|
||||||
|
Qt.Key.Key_Plus,
|
||||||
|
Qt.Key.Key_Equal,
|
||||||
|
):
|
||||||
self.main_window.zoom_in()
|
self.main_window.zoom_in()
|
||||||
return True # consume event
|
return True # consume event
|
||||||
|
|
||||||
# Zoom out: Ctrl+Shift+Minus
|
# Zoom out: Ctrl+Shift+Minus
|
||||||
# Note: On some keyboards Shift+Minus produces '_' (Underscore)
|
# Note: On some keyboards Shift+Minus produces '_' (Underscore)
|
||||||
elif key in (Qt.Key.Key_Minus, Qt.Key.Key_Underscore):
|
elif key in (
|
||||||
|
Qt.Key.Key_Minus,
|
||||||
|
Qt.Key.Key_Underscore,
|
||||||
|
):
|
||||||
self.main_window.zoom_out()
|
self.main_window.zoom_out()
|
||||||
return True # consume event
|
return True # consume event
|
||||||
|
|
||||||
# Reset zoom: Ctrl+Shift+0
|
# Reset zoom: Ctrl+Shift+0
|
||||||
# Note: On some keyboards Shift+0 produces ')' (ParenRight)
|
# Note: On some keyboards Shift+0 produces ')' (ParenRight)
|
||||||
elif key in (Qt.Key.Key_0, Qt.Key.Key_ParenRight):
|
elif key in (
|
||||||
|
Qt.Key.Key_0,
|
||||||
|
Qt.Key.Key_ParenRight,
|
||||||
|
):
|
||||||
self.main_window.reset_zoom()
|
self.main_window.reset_zoom()
|
||||||
return True # consume event
|
return True # consume event
|
||||||
|
|
||||||
|
|
@ -117,6 +141,7 @@ class GlobalZoomEventFilter(QObject):
|
||||||
|
|
||||||
|
|
||||||
class MultiStatus:
|
class MultiStatus:
|
||||||
|
|
||||||
bar: QStatusBar
|
bar: QStatusBar
|
||||||
statuses: list[str]
|
statuses: list[str]
|
||||||
|
|
||||||
|
|
@ -127,17 +152,19 @@ class MultiStatus:
|
||||||
self._status_groups: dict[str, (set, Callable)] = {}
|
self._status_groups: dict[str, (set, Callable)] = {}
|
||||||
|
|
||||||
def open_status(
|
def open_status(
|
||||||
|
|
||||||
self,
|
self,
|
||||||
msg: str,
|
msg: str,
|
||||||
final_msg: str | None = None,
|
final_msg: str|None = None,
|
||||||
clear_on_next: bool = False,
|
clear_on_next: bool = False,
|
||||||
group_key: Union[bool, str] | None = False,
|
group_key: Union[bool, str]|None = False,
|
||||||
|
|
||||||
) -> Union[Callable[..., None], str]:
|
) -> Union[Callable[..., None], str]:
|
||||||
"""
|
'''
|
||||||
Add a status to the status bar and return a close callback which
|
Add a status to the status bar and return a close callback which
|
||||||
when called will remove the status ``msg``.
|
when called will remove the status ``msg``.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
for old_msg in self._to_clear:
|
for old_msg in self._to_clear:
|
||||||
try:
|
try:
|
||||||
self.statuses.remove(old_msg)
|
self.statuses.remove(old_msg)
|
||||||
|
|
@ -216,10 +243,10 @@ class MultiStatus:
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def render(self) -> None:
|
def render(self) -> None:
|
||||||
"""
|
'''
|
||||||
Display all open statuses to bar.
|
Display all open statuses to bar.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
if self.statuses:
|
if self.statuses:
|
||||||
self.bar.showMessage(f'{" ".join(self.statuses)}')
|
self.bar.showMessage(f'{" ".join(self.statuses)}')
|
||||||
else:
|
else:
|
||||||
|
|
@ -227,6 +254,7 @@ class MultiStatus:
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
|
|
||||||
# XXX: for tiling wms this should scale
|
# XXX: for tiling wms this should scale
|
||||||
# with the alloted window size.
|
# with the alloted window size.
|
||||||
# TODO: detect for tiling and if untrue set some size?
|
# TODO: detect for tiling and if untrue set some size?
|
||||||
|
|
@ -241,11 +269,11 @@ class MainWindow(QMainWindow):
|
||||||
self.setWindowTitle(self.title)
|
self.setWindowTitle(self.title)
|
||||||
|
|
||||||
# set by runtime after `trio` is engaged.
|
# set by runtime after `trio` is engaged.
|
||||||
self.godwidget: GodWidget | None = None
|
self.godwidget: GodWidget|None = None
|
||||||
|
|
||||||
self._status_bar: QStatusBar = None
|
self._status_bar: QStatusBar = None
|
||||||
self._status_label: QLabel = None
|
self._status_label: QLabel = None
|
||||||
self._size: tuple[int, int] | None = None
|
self._size: tuple[int, int]|None = None
|
||||||
|
|
||||||
# restore window geometry from previous session
|
# restore window geometry from previous session
|
||||||
settings = QSettings('pikers', 'piker')
|
settings = QSettings('pikers', 'piker')
|
||||||
|
|
@ -265,7 +293,7 @@ class MainWindow(QMainWindow):
|
||||||
self._zoom_filter: GlobalZoomEventFilter | None = None
|
self._zoom_filter: GlobalZoomEventFilter | None = None
|
||||||
|
|
||||||
def install_global_zoom_filter(self) -> None:
|
def install_global_zoom_filter(self) -> None:
|
||||||
"""Install application-level event filter for global UI zoom shortcuts."""
|
'''Install application-level event filter for global UI zoom shortcuts.'''
|
||||||
if self._zoom_filter is None:
|
if self._zoom_filter is None:
|
||||||
self._zoom_filter = GlobalZoomEventFilter(self)
|
self._zoom_filter = GlobalZoomEventFilter(self)
|
||||||
app = QApplication.instance()
|
app = QApplication.instance()
|
||||||
|
|
@ -277,6 +305,7 @@ class MainWindow(QMainWindow):
|
||||||
|
|
||||||
# init mode label
|
# init mode label
|
||||||
if not self._status_label:
|
if not self._status_label:
|
||||||
|
|
||||||
self._status_label = label = QLabel()
|
self._status_label = label = QLabel()
|
||||||
label.setStyleSheet(
|
label.setStyleSheet(
|
||||||
f"""QLabel {{
|
f"""QLabel {{
|
||||||
|
|
@ -285,10 +314,15 @@ class MainWindow(QMainWindow):
|
||||||
"""
|
"""
|
||||||
# font-size : {font_size}px;
|
# font-size : {font_size}px;
|
||||||
)
|
)
|
||||||
label.setTextFormat(Qt.TextFormat.MarkdownText)
|
label.setTextFormat(
|
||||||
|
Qt.TextFormat.MarkdownText
|
||||||
|
)
|
||||||
label.setFont(_font_small.font)
|
label.setFont(_font_small.font)
|
||||||
label.setMargin(2)
|
label.setMargin(2)
|
||||||
label.setAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignRight)
|
label.setAlignment(
|
||||||
|
QtCore.Qt.AlignVCenter
|
||||||
|
|QtCore.Qt.AlignRight
|
||||||
|
)
|
||||||
self.statusBar().addPermanentWidget(label)
|
self.statusBar().addPermanentWidget(label)
|
||||||
label.show()
|
label.show()
|
||||||
|
|
||||||
|
|
@ -297,8 +331,11 @@ class MainWindow(QMainWindow):
|
||||||
def closeEvent(
|
def closeEvent(
|
||||||
self,
|
self,
|
||||||
event: QCloseEvent,
|
event: QCloseEvent,
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Cancel the root actor asap."""
|
'''Cancel the root actor asap.
|
||||||
|
|
||||||
|
'''
|
||||||
# save window geometry for next session
|
# save window geometry for next session
|
||||||
settings = QSettings('pikers', 'piker')
|
settings = QSettings('pikers', 'piker')
|
||||||
settings.setValue('windowGeometry', self.saveGeometry())
|
settings.setValue('windowGeometry', self.saveGeometry())
|
||||||
|
|
@ -312,17 +349,16 @@ class MainWindow(QMainWindow):
|
||||||
|
|
||||||
# style and cached the status bar on first access
|
# style and cached the status bar on first access
|
||||||
if not self._status_bar:
|
if not self._status_bar:
|
||||||
|
|
||||||
sb = self.statusBar()
|
sb = self.statusBar()
|
||||||
sb.setStyleSheet(
|
sb.setStyleSheet((
|
||||||
(
|
f"color : {hcolor('gunmetal')};"
|
||||||
f'color : {hcolor("gunmetal")};'
|
f"background : {hcolor('default_dark')};"
|
||||||
f'background : {hcolor("default_dark")};'
|
f"font-size : {_font_small.px_size}px;"
|
||||||
f'font-size : {_font_small.px_size}px;'
|
"padding : 0px;"
|
||||||
'padding : 0px;'
|
# "min-height : 19px;"
|
||||||
# "min-height : 19px;"
|
# "qproperty-alignment: AlignVCenter;"
|
||||||
# "qproperty-alignment: AlignVCenter;"
|
))
|
||||||
)
|
|
||||||
)
|
|
||||||
self.setStatusBar(sb)
|
self.setStatusBar(sb)
|
||||||
self._status_bar = MultiStatus(sb, [])
|
self._status_bar = MultiStatus(sb, [])
|
||||||
|
|
||||||
|
|
@ -331,22 +367,28 @@ class MainWindow(QMainWindow):
|
||||||
def set_mode_name(
|
def set_mode_name(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
self.mode_label.setText(f'mode:{name}')
|
self.mode_label.setText(f'mode:{name}')
|
||||||
|
|
||||||
def on_focus_change(
|
def on_focus_change(
|
||||||
self,
|
self,
|
||||||
|
|
||||||
last: QWidget,
|
last: QWidget,
|
||||||
current: QWidget,
|
current: QWidget,
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
'''
|
||||||
Focus handler.
|
Focus handler.
|
||||||
|
|
||||||
For now updates the "current mode" name.
|
For now updates the "current mode" name.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
log.debug(f'widget focus changed from,\n{last} -> {current}')
|
log.debug(
|
||||||
|
f'widget focus changed from,\n'
|
||||||
|
f'{last} -> {current}'
|
||||||
|
)
|
||||||
|
|
||||||
if current is not None:
|
if current is not None:
|
||||||
# cursor left window?
|
# cursor left window?
|
||||||
|
|
@ -354,10 +396,10 @@ class MainWindow(QMainWindow):
|
||||||
self.set_mode_name(name)
|
self.set_mode_name(name)
|
||||||
|
|
||||||
def current_screen(self) -> QScreen:
|
def current_screen(self) -> QScreen:
|
||||||
"""
|
'''
|
||||||
Get a frickin screen (if we can, gawd).
|
Get a frickin screen (if we can, gawd).
|
||||||
|
|
||||||
"""
|
'''
|
||||||
app = QApplication.instance()
|
app = QApplication.instance()
|
||||||
|
|
||||||
for _ in range(3):
|
for _ in range(3):
|
||||||
|
|
@ -373,28 +415,29 @@ class MainWindow(QMainWindow):
|
||||||
# try for the first one we can find
|
# try for the first one we can find
|
||||||
screen = app.screens()[0]
|
screen = app.screens()[0]
|
||||||
|
|
||||||
assert screen, 'Wow Qt is dumb as shit and has no screen...'
|
assert screen, "Wow Qt is dumb as shit and has no screen..."
|
||||||
return screen
|
return screen
|
||||||
|
|
||||||
def configure_to_desktop(
|
def configure_to_desktop(
|
||||||
self,
|
self,
|
||||||
size: tuple[int, int] | None = None,
|
size: tuple[int, int]|None = None,
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
'''
|
||||||
Explicitly size the window dimensions (for stacked window
|
Explicitly size the window dimensions (for stacked window
|
||||||
managers).
|
managers).
|
||||||
|
|
||||||
For tina systems (like windoze) try to do a sane window size on
|
For tina systems (like windoze) try to do a sane window size on
|
||||||
startup.
|
startup.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
# https://stackoverflow.com/a/18975846
|
# https://stackoverflow.com/a/18975846
|
||||||
if not size and not self._size:
|
if not size and not self._size:
|
||||||
# app = QApplication.instance()
|
# app = QApplication.instance()
|
||||||
geo = self.current_screen().geometry()
|
geo = self.current_screen().geometry()
|
||||||
h, w = geo.height(), geo.width()
|
h, w = geo.height(), geo.width()
|
||||||
# use approx 1/3 of the area of the screen by default
|
# use approx 1/3 of the area of the screen by default
|
||||||
self._size = round(w * 0.666), round(h * 0.666)
|
self._size = round(w * .666), round(h * .666)
|
||||||
|
|
||||||
self.resize(*size or self._size)
|
self.resize(*size or self._size)
|
||||||
|
|
||||||
|
|
@ -426,46 +469,79 @@ class MainWindow(QMainWindow):
|
||||||
event.accept()
|
event.accept()
|
||||||
|
|
||||||
def zoom_in(self) -> None:
|
def zoom_in(self) -> None:
|
||||||
"""Increase UI zoom level."""
|
'''
|
||||||
new_zoom = min(self._zoom_level + self._zoom_step, self._max_zoom)
|
Increase overall UI-widgets zoom level by scaling it the
|
||||||
if new_zoom != self._zoom_level:
|
global font sizes.
|
||||||
self._zoom_level = new_zoom
|
|
||||||
self._apply_zoom()
|
|
||||||
log.info(f'Zoomed in to {self._zoom_level:.1%}')
|
|
||||||
|
|
||||||
def zoom_out(self) -> None:
|
'''
|
||||||
"""Decrease UI zoom level."""
|
new_zoom: float = min(
|
||||||
new_zoom = max(self._zoom_level - self._zoom_step, self._min_zoom)
|
self._zoom_level + self._zoom_step,
|
||||||
|
self._max_zoom,
|
||||||
|
)
|
||||||
if new_zoom != self._zoom_level:
|
if new_zoom != self._zoom_level:
|
||||||
self._zoom_level = new_zoom
|
self._zoom_level = new_zoom
|
||||||
self._apply_zoom()
|
font_size: int = self._apply_zoom()
|
||||||
log.info(f'Zoomed out to {self._zoom_level:.1%}')
|
log.info(
|
||||||
|
f'Zoomed in UI\n'
|
||||||
|
f'zoom_step: {self._zoom_step!r}\n'
|
||||||
|
f'zoom_level(%): {self._zoom_level:.1%}\n'
|
||||||
|
f'font_size: {font_size!r}'
|
||||||
|
)
|
||||||
|
|
||||||
|
def zoom_out(self) -> float:
|
||||||
|
'''
|
||||||
|
Decrease UI zoom level.
|
||||||
|
|
||||||
|
'''
|
||||||
|
new_zoom: float = max(self._zoom_level - self._zoom_step, self._min_zoom)
|
||||||
|
if new_zoom != self._zoom_level:
|
||||||
|
self._zoom_level = new_zoom
|
||||||
|
font_size: int = self._apply_zoom()
|
||||||
|
log.info(
|
||||||
|
f'Zoomed out UI\n'
|
||||||
|
f'zoom_step: {self._zoom_step!r}\n'
|
||||||
|
f'zoom_level(%): {self._zoom_level:.1%}\n'
|
||||||
|
f'font_size: {font_size!r}'
|
||||||
|
)
|
||||||
|
|
||||||
|
return new_zoom
|
||||||
|
|
||||||
def reset_zoom(self) -> None:
|
def reset_zoom(self) -> None:
|
||||||
"""Reset UI zoom to 100%."""
|
'''
|
||||||
|
Reset UI zoom to 100%.
|
||||||
|
|
||||||
|
'''
|
||||||
if self._zoom_level != 1.0:
|
if self._zoom_level != 1.0:
|
||||||
self._zoom_level = 1.0
|
self._zoom_level = 1.0
|
||||||
self._apply_zoom()
|
font_size: int = self._apply_zoom()
|
||||||
log.info('Reset zoom to 100%')
|
log.info(
|
||||||
|
f'Reset zoom level\n'
|
||||||
|
f'zoom_step: {self._zoom_step!r}\n'
|
||||||
|
f'zoom_level(%): {self._zoom_level:.1%}\n'
|
||||||
|
f'font_size: {font_size!r}'
|
||||||
|
)
|
||||||
|
|
||||||
def _apply_zoom(self) -> None:
|
return self._zoom_level
|
||||||
"""Apply current zoom level to all UI elements."""
|
|
||||||
from . import _style
|
|
||||||
|
|
||||||
|
def _apply_zoom(self) -> int:
|
||||||
|
'''
|
||||||
|
Apply current zoom level to all UI elements.
|
||||||
|
|
||||||
|
'''
|
||||||
# reconfigure fonts with zoom multiplier
|
# reconfigure fonts with zoom multiplier
|
||||||
_style._config_fonts_to_screen(zoom_level=self._zoom_level)
|
font_size: int = _style._config_fonts_to_screen(
|
||||||
|
zoom_level=self._zoom_level
|
||||||
|
)
|
||||||
|
|
||||||
# update status bar styling with new font size
|
# update status bar styling with new font size
|
||||||
if self._status_bar:
|
if self._status_bar:
|
||||||
sb = self.statusBar()
|
sb = self.statusBar()
|
||||||
sb.setStyleSheet(
|
sb.setStyleSheet((
|
||||||
(
|
f"color : {hcolor('gunmetal')};"
|
||||||
f'color : {hcolor("gunmetal")};'
|
f"background : {hcolor('default_dark')};"
|
||||||
f'background : {hcolor("default_dark")};'
|
f"font-size : {_style._font_small.px_size}px;"
|
||||||
f'font-size : {_style._font_small.px_size}px;'
|
"padding : 0px;"
|
||||||
'padding : 0px;'
|
))
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# force update of mode label if it exists
|
# force update of mode label if it exists
|
||||||
if self._status_label:
|
if self._status_label:
|
||||||
|
|
@ -484,8 +560,13 @@ class MainWindow(QMainWindow):
|
||||||
self._refresh_widget_fonts(self.godwidget)
|
self._refresh_widget_fonts(self.godwidget)
|
||||||
self.godwidget.update()
|
self.godwidget.update()
|
||||||
|
|
||||||
|
return font_size
|
||||||
|
|
||||||
def _update_chart_order_panes(self) -> None:
|
def _update_chart_order_panes(self) -> None:
|
||||||
"""Update order entry panels in all charts."""
|
'''
|
||||||
|
Update order entry panels in all charts.
|
||||||
|
|
||||||
|
'''
|
||||||
if not self.godwidget:
|
if not self.godwidget:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -520,10 +601,7 @@ class MainWindow(QMainWindow):
|
||||||
subplot_view = subplot_chart.view
|
subplot_view = subplot_chart.view
|
||||||
if hasattr(subplot_view, 'order_mode') and subplot_view.order_mode:
|
if hasattr(subplot_view, 'order_mode') and subplot_view.order_mode:
|
||||||
subplot_order_mode = subplot_view.order_mode
|
subplot_order_mode = subplot_view.order_mode
|
||||||
if (
|
if hasattr(subplot_order_mode, 'pane') and subplot_order_mode.pane:
|
||||||
hasattr(subplot_order_mode, 'pane')
|
|
||||||
and subplot_order_mode.pane
|
|
||||||
):
|
|
||||||
subplot_order_mode.pane.update_fonts()
|
subplot_order_mode.pane.update_fonts()
|
||||||
|
|
||||||
# resize all sidepanes to match main chart's sidepane width
|
# resize all sidepanes to match main chart's sidepane width
|
||||||
|
|
@ -532,7 +610,7 @@ class MainWindow(QMainWindow):
|
||||||
splits.resize_sidepanes()
|
splits.resize_sidepanes()
|
||||||
|
|
||||||
def _update_chart_axes(self, chart) -> None:
|
def _update_chart_axes(self, chart) -> None:
|
||||||
"""Update axis fonts and sizing for a chart."""
|
'''Update axis fonts and sizing for a chart.'''
|
||||||
from . import _style
|
from . import _style
|
||||||
|
|
||||||
# update price axis (right side)
|
# update price axis (right side)
|
||||||
|
|
@ -556,11 +634,11 @@ class MainWindow(QMainWindow):
|
||||||
chart.update()
|
chart.update()
|
||||||
|
|
||||||
def _refresh_widget_fonts(self, widget: QWidget) -> None:
|
def _refresh_widget_fonts(self, widget: QWidget) -> None:
|
||||||
"""
|
'''
|
||||||
Recursively update font sizes in all child widgets.
|
Recursively update font sizes in all child widgets.
|
||||||
|
|
||||||
This handles widgets that have font-size hardcoded in their stylesheets.
|
This handles widgets that have font-size hardcoded in their stylesheets.
|
||||||
"""
|
'''
|
||||||
from . import _style
|
from . import _style
|
||||||
|
|
||||||
# recursively process all children
|
# recursively process all children
|
||||||
|
|
@ -591,7 +669,7 @@ _qt_win: QMainWindow = None
|
||||||
|
|
||||||
|
|
||||||
def main_window() -> MainWindow:
|
def main_window() -> MainWindow:
|
||||||
"Return the actor-global Qt window."
|
'Return the actor-global Qt window.'
|
||||||
|
|
||||||
global _qt_win
|
global _qt_win
|
||||||
assert _qt_win
|
assert _qt_win
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue