feat: show zoom percentage in statusbar resolving #2870

This commit is contained in:
Skeptic Spriggan 2025-10-21 10:13:15 +02:00
parent 67db09a9c9
commit fa78054d37
10 changed files with 98 additions and 3 deletions

View File

@ -25,6 +25,7 @@ Added
- The `:version` info now shows the X11 window manager / Wayland compositor name
(mostly useful for bug/crash reports).
- Support for hinting elements which are part of an (open) shadow DOM.
- Show zoom percentage in statusbar. (#2870)
Changed
~~~~~~~

View File

@ -434,6 +434,9 @@ class AbstractZoom(QObject):
"""Attribute ``zoom`` of AbstractTab for controlling zoom."""
#: Signal emitted when a tab's zoom factor changed (float)
factor_changed = pyqtSignal(float)
def __init__(self, tab: 'AbstractTab', parent: QWidget = None) -> None:
super().__init__(parent)
self._tab = tab

View File

@ -730,6 +730,7 @@ class WebEngineZoom(browsertab.AbstractZoom):
def _set_factor_internal(self, factor):
self._widget.setZoomFactor(factor)
self.factor_changed.emit(factor)
class WebEngineElements(browsertab.AbstractElements):

View File

@ -2195,6 +2195,7 @@ statusbar.widgets:
format string via `clock:...`. For supported format strings, see
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes[the
Python datetime documentation]."
- zoom: "Display zoom percentage (e.g. `200%`)"
none_ok: true
default: ['keypress', 'search_match', 'url', 'scroll', 'history', 'tabs', 'progress']
desc: "List of widgets displayed in the statusbar."

View File

@ -525,6 +525,8 @@ class MainWindow(QWidget):
self.tabbed_browser.cur_scroll_perc_changed.connect(
self.status.percentage.set_perc)
self.tabbed_browser.cur_zoom_changed.connect(
self.status.zoom.on_zoom_changed)
self.tabbed_browser.widget.tab_index_changed.connect(
self.status.tabindex.on_tab_index_changed)

View File

@ -16,7 +16,8 @@ from qutebrowser.keyinput import modeman
from qutebrowser.utils import usertypes, log, objreg, utils
from qutebrowser.mainwindow.statusbar import (backforward, command, progress,
keystring, percentage, url,
tabindex, textbase, clock, searchmatch)
tabindex, textbase, clock, searchmatch,
zoom)
@dataclasses.dataclass
@ -190,6 +191,7 @@ class StatusBar(QWidget):
self.keystring = keystring.KeyString()
self.prog = progress.Progress(self)
self.clock = clock.Clock()
self.zoom = zoom.Zoom()
self._text_widgets = []
self._draw_widgets()
@ -223,6 +225,8 @@ class StatusBar(QWidget):
return new_text_widget
elif key.startswith('clock:') or key == 'clock':
return self.clock
elif key == 'zoom':
return self.zoom
else:
raise utils.Unreachable(key)
@ -272,7 +276,8 @@ class StatusBar(QWidget):
# Start with widgets hidden and show them when needed
for widget in [self.url, self.percentage,
self.backforward, self.tabindex,
self.keystring, self.prog, self.clock, *self._text_widgets]:
self.keystring, self.prog, self.clock,
self.zoom, *self._text_widgets]:
assert isinstance(widget, QWidget)
if widget in [self.prog, self.backforward]:
widget.enabled = False # type: ignore[attr-defined]
@ -426,6 +431,7 @@ class StatusBar(QWidget):
self.prog.on_tab_changed(tab)
self.percentage.on_tab_changed(tab)
self.backforward.on_tab_changed(tab)
self.zoom.on_tab_changed(tab)
self.maybe_hide()
assert tab.is_private == self._color_flags.private

View File

@ -0,0 +1,24 @@
"""Zoom percentage displayed in the statusbar."""
from qutebrowser.mainwindow.statusbar import textbase
from qutebrowser.qt.core import pyqtSlot
class Zoom(textbase.TextBase):
"""Shows percentage indicator."""
def __init__(self, parent=None):
super().__init__(parent)
self.setText("100%")
@pyqtSlot(float)
def on_zoom_changed(self, factor):
percentage = int(100 * factor)
self.setText(f"{percentage}%")
def on_tab_changed(self, tab):
"""Update zoom when tab changed."""
percentage = int(100 * tab.zoom.factor())
self.setText(f"{percentage}%")

View File

@ -168,6 +168,7 @@ class TabbedBrowser(QWidget):
cur_load_started: Current tab started loading (load_started)
cur_load_finished: Current tab finished loading (load_finished)
cur_url_changed: Current URL changed.
cur_zoom_changed: Zoom factor of current tab changed.
cur_link_hovered: Link hovered in current tab (link_hovered)
cur_scroll_perc_changed: Scroll percentage of current tab changed.
arg 1: x-position in %.
@ -189,6 +190,7 @@ class TabbedBrowser(QWidget):
cur_url_changed = pyqtSignal(QUrl)
cur_link_hovered = pyqtSignal(str)
cur_scroll_perc_changed = pyqtSignal(int, int)
cur_zoom_changed = pyqtSignal(float)
cur_load_status_changed = pyqtSignal(usertypes.LoadStatus)
cur_search_match_changed = pyqtSignal(browsertab.SearchMatch)
cur_fullscreen_requested = pyqtSignal(bool)
@ -337,6 +339,8 @@ class TabbedBrowser(QWidget):
self._filter.create(self.cur_load_started, tab))
tab.scroller.perc_changed.connect(
self._filter.create(self.cur_scroll_perc_changed, tab))
tab.zoom.factor_changed.connect(
self._filter.create(self.cur_zoom_changed, tab))
tab.url_changed.connect(
self._filter.create(self.cur_url_changed, tab))
tab.load_status_changed.connect(

View File

@ -204,6 +204,17 @@ class FakeWebTabScroller(browsertab.AbstractScroller):
def pos_perc(self):
return self._pos_perc
class FakeWebTabZoom(browsertab.AbstractZoom):
"""Fake AbstractZoom to use in tests."""
def __init__(self, tab, factor):
super().__init__(tab)
self._factor = factor
def factor(self):
return self._factor
class FakeWebTabHistory(browsertab.AbstractHistory):
@ -245,7 +256,8 @@ class FakeWebTab(browsertab.AbstractTab):
def __init__(self, url=QUrl(), title='', tab_id=0, *,
scroll_pos_perc=(0, 0),
load_status=usertypes.LoadStatus.success,
progress=0, can_go_back=None, can_go_forward=None):
progress=0, can_go_back=None, can_go_forward=None,
zoom_factor=1):
super().__init__(win_id=0, mode_manager=None, private=False)
self._load_status = load_status
self._title = title
@ -254,6 +266,7 @@ class FakeWebTab(browsertab.AbstractTab):
self.history = FakeWebTabHistory(self, can_go_back=can_go_back,
can_go_forward=can_go_forward)
self.scroller = FakeWebTabScroller(self, scroll_pos_perc)
self.zoom = FakeWebTabZoom(self, zoom_factor)
self.audio = FakeWebTabAudio(self)
self.private_api = FakeWebTabPrivate(tab=self, mode_manager=None)
wrapped = QWidget()

View File

@ -0,0 +1,40 @@
"""Test Zoom widget."""
import pytest
from qutebrowser.mainwindow.statusbar.zoom import Zoom
@pytest.fixture
def zoom(qtbot):
"""Fixture providing a Percentage widget."""
widget = Zoom()
qtbot.add_widget(widget)
return widget
@pytest.mark.parametrize('factor, expected', [
(1, '100%'),
(1.5, '150%'),
(2, '200%'),
(0.5, '50%'),
(0.25, '25%'),
])
def test_percentage_texts(zoom, factor, expected):
"""Test text displayed by the widget based on the zoom factor of a tab.
Args:
factor: zoom factor of the tab as a float.
expected: expected text given factor.
"""
zoom.on_zoom_changed(factor=factor)
assert zoom.text() == expected
def test_tab_change(zoom, fake_web_tab):
"""Test zoom factor change when switching tabs."""
zoom.on_zoom_changed(factor=2)
assert zoom.text() == '200%'
tab = fake_web_tab(zoom_factor=0.5)
zoom.on_tab_changed(tab)
assert zoom.text() == '50%'