Merge bc42d5c3be into 7e3df43463
This commit is contained in:
commit
ce38941742
|
|
@ -82,6 +82,7 @@ Added
|
||||||
* Loaded WebExtensions (partial support landed in QtWebEngine 6.10, no
|
* Loaded WebExtensions (partial support landed in QtWebEngine 6.10, no
|
||||||
official qutebrowser support yet).
|
official qutebrowser support yet).
|
||||||
- Support for hinting elements which are part of an (open) shadow DOM.
|
- Support for hinting elements which are part of an (open) shadow DOM.
|
||||||
|
- Show zoom percentage in statusbar. (#2870)
|
||||||
|
|
||||||
Changed
|
Changed
|
||||||
~~~~~~~
|
~~~~~~~
|
||||||
|
|
|
||||||
|
|
@ -434,6 +434,9 @@ class AbstractZoom(QObject):
|
||||||
|
|
||||||
"""Attribute ``zoom`` of AbstractTab for controlling zoom."""
|
"""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:
|
def __init__(self, tab: 'AbstractTab', parent: QWidget = None) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._tab = tab
|
self._tab = tab
|
||||||
|
|
|
||||||
|
|
@ -728,8 +728,20 @@ class WebEngineZoom(browsertab.AbstractZoom):
|
||||||
|
|
||||||
_widget: webview.WebEngineView
|
_widget: webview.WebEngineView
|
||||||
|
|
||||||
|
def connect_signals(self):
|
||||||
|
"""Called from WebEngineTab.connect_signals."""
|
||||||
|
page = self._widget.page()
|
||||||
|
if machinery.IS_QT6:
|
||||||
|
try:
|
||||||
|
page.zoomFactorChanged.connect(self.factor_changed)
|
||||||
|
except AttributeError:
|
||||||
|
# Added in Qt 6.8
|
||||||
|
pass
|
||||||
|
|
||||||
def _set_factor_internal(self, factor):
|
def _set_factor_internal(self, factor):
|
||||||
self._widget.setZoomFactor(factor)
|
self._widget.setZoomFactor(factor)
|
||||||
|
if not hasattr(self._widget.page(), "zoomFactorChanged"):
|
||||||
|
self.factor_changed.emit(factor)
|
||||||
|
|
||||||
|
|
||||||
class WebEngineElements(browsertab.AbstractElements):
|
class WebEngineElements(browsertab.AbstractElements):
|
||||||
|
|
@ -1286,6 +1298,7 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||||
search: WebEngineSearch
|
search: WebEngineSearch
|
||||||
audio: WebEngineAudio
|
audio: WebEngineAudio
|
||||||
printing: WebEnginePrinting
|
printing: WebEnginePrinting
|
||||||
|
zoom: WebEngineZoom
|
||||||
|
|
||||||
def __init__(self, *, win_id, mode_manager, private, parent=None):
|
def __init__(self, *, win_id, mode_manager, private, parent=None):
|
||||||
super().__init__(win_id=win_id,
|
super().__init__(win_id=win_id,
|
||||||
|
|
@ -1760,5 +1773,6 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||||
self.audio._connect_signals()
|
self.audio._connect_signals()
|
||||||
self.search.connect_signals()
|
self.search.connect_signals()
|
||||||
self.printing.connect_signals()
|
self.printing.connect_signals()
|
||||||
|
self.zoom.connect_signals()
|
||||||
self._permissions.connect_signals()
|
self._permissions.connect_signals()
|
||||||
self._scripts.connect_signals()
|
self._scripts.connect_signals()
|
||||||
|
|
|
||||||
|
|
@ -2208,10 +2208,21 @@ statusbar.widgets:
|
||||||
format string via `clock:...`. For supported format strings, see
|
format string via `clock:...`. For supported format strings, see
|
||||||
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes[the
|
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes[the
|
||||||
Python datetime documentation]."
|
Python datetime documentation]."
|
||||||
|
- zoom: "Display zoom percentage (e.g. `200%`)"
|
||||||
none_ok: true
|
none_ok: true
|
||||||
default: ['keypress', 'search_match', 'url', 'scroll', 'history', 'tabs', 'progress']
|
default: ['keypress', 'search_match', 'url', 'zoom', 'scroll',
|
||||||
|
'history', 'tabs', 'progress']
|
||||||
desc: "List of widgets displayed in the statusbar."
|
desc: "List of widgets displayed in the statusbar."
|
||||||
|
|
||||||
|
statusbar.zoom.show:
|
||||||
|
default: non-default
|
||||||
|
type:
|
||||||
|
name: String
|
||||||
|
valid_values:
|
||||||
|
- always: Always show the zoom percentage.
|
||||||
|
- non-default: Show the zoom percentage when it is not 100%.
|
||||||
|
desc: When to show the zoom percentage in the statusbar.
|
||||||
|
|
||||||
## tabs
|
## tabs
|
||||||
|
|
||||||
tabs.background:
|
tabs.background:
|
||||||
|
|
|
||||||
|
|
@ -525,6 +525,8 @@ class MainWindow(QWidget):
|
||||||
|
|
||||||
self.tabbed_browser.cur_scroll_perc_changed.connect(
|
self.tabbed_browser.cur_scroll_perc_changed.connect(
|
||||||
self.status.percentage.set_perc)
|
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.tabbed_browser.widget.tab_index_changed.connect(
|
||||||
self.status.tabindex.on_tab_index_changed)
|
self.status.tabindex.on_tab_index_changed)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ from qutebrowser.keyinput import modeman
|
||||||
from qutebrowser.utils import usertypes, log, objreg, utils
|
from qutebrowser.utils import usertypes, log, objreg, utils
|
||||||
from qutebrowser.mainwindow.statusbar import (backforward, command, progress,
|
from qutebrowser.mainwindow.statusbar import (backforward, command, progress,
|
||||||
keystring, percentage, url,
|
keystring, percentage, url,
|
||||||
tabindex, textbase, clock, searchmatch)
|
tabindex, textbase, clock, searchmatch,
|
||||||
|
zoom)
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
|
|
@ -190,6 +191,7 @@ class StatusBar(QWidget):
|
||||||
self.keystring = keystring.KeyString()
|
self.keystring = keystring.KeyString()
|
||||||
self.prog = progress.Progress(self)
|
self.prog = progress.Progress(self)
|
||||||
self.clock = clock.Clock()
|
self.clock = clock.Clock()
|
||||||
|
self.zoom = zoom.Zoom()
|
||||||
self._text_widgets = []
|
self._text_widgets = []
|
||||||
self._draw_widgets()
|
self._draw_widgets()
|
||||||
|
|
||||||
|
|
@ -223,6 +225,8 @@ class StatusBar(QWidget):
|
||||||
return new_text_widget
|
return new_text_widget
|
||||||
elif key.startswith('clock:') or key == 'clock':
|
elif key.startswith('clock:') or key == 'clock':
|
||||||
return self.clock
|
return self.clock
|
||||||
|
elif key == 'zoom':
|
||||||
|
return self.zoom
|
||||||
else:
|
else:
|
||||||
raise utils.Unreachable(key)
|
raise utils.Unreachable(key)
|
||||||
|
|
||||||
|
|
@ -248,7 +252,7 @@ class StatusBar(QWidget):
|
||||||
|
|
||||||
if segment == 'scroll_raw':
|
if segment == 'scroll_raw':
|
||||||
widget.set_raw()
|
widget.set_raw()
|
||||||
elif segment in ('history', 'progress'):
|
elif segment in ('history', 'progress', 'zoom'):
|
||||||
widget.enabled = True
|
widget.enabled = True
|
||||||
if tab:
|
if tab:
|
||||||
widget.on_tab_changed(tab)
|
widget.on_tab_changed(tab)
|
||||||
|
|
@ -272,7 +276,8 @@ class StatusBar(QWidget):
|
||||||
# Start with widgets hidden and show them when needed
|
# Start with widgets hidden and show them when needed
|
||||||
for widget in [self.url, self.percentage,
|
for widget in [self.url, self.percentage,
|
||||||
self.backforward, self.tabindex,
|
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)
|
assert isinstance(widget, QWidget)
|
||||||
if widget in [self.prog, self.backforward]:
|
if widget in [self.prog, self.backforward]:
|
||||||
widget.enabled = False # type: ignore[attr-defined]
|
widget.enabled = False # type: ignore[attr-defined]
|
||||||
|
|
@ -423,6 +428,7 @@ class StatusBar(QWidget):
|
||||||
self.prog.on_tab_changed(tab)
|
self.prog.on_tab_changed(tab)
|
||||||
self.percentage.on_tab_changed(tab)
|
self.percentage.on_tab_changed(tab)
|
||||||
self.backforward.on_tab_changed(tab)
|
self.backforward.on_tab_changed(tab)
|
||||||
|
self.zoom.on_tab_changed(tab)
|
||||||
self.maybe_hide()
|
self.maybe_hide()
|
||||||
assert tab.is_private == self._color_flags.private
|
assert tab.is_private == self._color_flags.private
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
"""Zoom percentage displayed in the statusbar."""
|
||||||
|
|
||||||
|
from qutebrowser.browser import browsertab
|
||||||
|
from qutebrowser.mainwindow.statusbar import textbase
|
||||||
|
from qutebrowser.qt.core import pyqtSlot, QObject
|
||||||
|
from qutebrowser.config import config
|
||||||
|
|
||||||
|
|
||||||
|
class Zoom(textbase.TextBase):
|
||||||
|
|
||||||
|
"""Shows zoom percentage in current tab."""
|
||||||
|
|
||||||
|
def __init__(self, parent: QObject = None) -> None:
|
||||||
|
super().__init__(parent)
|
||||||
|
self.on_zoom_changed(1)
|
||||||
|
|
||||||
|
@pyqtSlot(float)
|
||||||
|
def on_zoom_changed(self, factor: float) -> None:
|
||||||
|
"""Update percentage when factor changed."""
|
||||||
|
if factor == 1 and config.val.statusbar.zoom.show == 'non-default':
|
||||||
|
self.hide()
|
||||||
|
return
|
||||||
|
self.show()
|
||||||
|
percentage = round(100 * factor)
|
||||||
|
self.setText(f"[{percentage}%]")
|
||||||
|
|
||||||
|
def on_tab_changed(self, tab: browsertab.AbstractTab) -> None:
|
||||||
|
"""Update percentage when tab changed."""
|
||||||
|
self.on_zoom_changed(tab.zoom.factor())
|
||||||
|
|
@ -168,6 +168,7 @@ class TabbedBrowser(QWidget):
|
||||||
cur_load_started: Current tab started loading (load_started)
|
cur_load_started: Current tab started loading (load_started)
|
||||||
cur_load_finished: Current tab finished loading (load_finished)
|
cur_load_finished: Current tab finished loading (load_finished)
|
||||||
cur_url_changed: Current URL changed.
|
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_link_hovered: Link hovered in current tab (link_hovered)
|
||||||
cur_scroll_perc_changed: Scroll percentage of current tab changed.
|
cur_scroll_perc_changed: Scroll percentage of current tab changed.
|
||||||
arg 1: x-position in %.
|
arg 1: x-position in %.
|
||||||
|
|
@ -189,6 +190,7 @@ class TabbedBrowser(QWidget):
|
||||||
cur_url_changed = pyqtSignal(QUrl)
|
cur_url_changed = pyqtSignal(QUrl)
|
||||||
cur_link_hovered = pyqtSignal(str)
|
cur_link_hovered = pyqtSignal(str)
|
||||||
cur_scroll_perc_changed = pyqtSignal(int, int)
|
cur_scroll_perc_changed = pyqtSignal(int, int)
|
||||||
|
cur_zoom_changed = pyqtSignal(float)
|
||||||
cur_load_status_changed = pyqtSignal(usertypes.LoadStatus)
|
cur_load_status_changed = pyqtSignal(usertypes.LoadStatus)
|
||||||
cur_search_match_changed = pyqtSignal(browsertab.SearchMatch)
|
cur_search_match_changed = pyqtSignal(browsertab.SearchMatch)
|
||||||
cur_fullscreen_requested = pyqtSignal(bool)
|
cur_fullscreen_requested = pyqtSignal(bool)
|
||||||
|
|
@ -337,6 +339,8 @@ class TabbedBrowser(QWidget):
|
||||||
self._filter.create(self.cur_load_started, tab))
|
self._filter.create(self.cur_load_started, tab))
|
||||||
tab.scroller.perc_changed.connect(
|
tab.scroller.perc_changed.connect(
|
||||||
self._filter.create(self.cur_scroll_perc_changed, tab))
|
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(
|
tab.url_changed.connect(
|
||||||
self._filter.create(self.cur_url_changed, tab))
|
self._filter.create(self.cur_url_changed, tab))
|
||||||
tab.load_status_changed.connect(
|
tab.load_status_changed.connect(
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,18 @@ class FakeWebTabScroller(browsertab.AbstractScroller):
|
||||||
return self._pos_perc
|
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):
|
class FakeWebTabHistory(browsertab.AbstractHistory):
|
||||||
|
|
||||||
"""Fake for Web{Kit,Engine}History."""
|
"""Fake for Web{Kit,Engine}History."""
|
||||||
|
|
@ -245,7 +257,8 @@ class FakeWebTab(browsertab.AbstractTab):
|
||||||
def __init__(self, url=QUrl(), title='', tab_id=0, *,
|
def __init__(self, url=QUrl(), title='', tab_id=0, *,
|
||||||
scroll_pos_perc=(0, 0),
|
scroll_pos_perc=(0, 0),
|
||||||
load_status=usertypes.LoadStatus.success,
|
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)
|
super().__init__(win_id=0, mode_manager=None, private=False)
|
||||||
self._load_status = load_status
|
self._load_status = load_status
|
||||||
self._title = title
|
self._title = title
|
||||||
|
|
@ -254,6 +267,7 @@ class FakeWebTab(browsertab.AbstractTab):
|
||||||
self.history = FakeWebTabHistory(self, can_go_back=can_go_back,
|
self.history = FakeWebTabHistory(self, can_go_back=can_go_back,
|
||||||
can_go_forward=can_go_forward)
|
can_go_forward=can_go_forward)
|
||||||
self.scroller = FakeWebTabScroller(self, scroll_pos_perc)
|
self.scroller = FakeWebTabScroller(self, scroll_pos_perc)
|
||||||
|
self.zoom = FakeWebTabZoom(self, zoom_factor)
|
||||||
self.audio = FakeWebTabAudio(self)
|
self.audio = FakeWebTabAudio(self)
|
||||||
self.private_api = FakeWebTabPrivate(tab=self, mode_manager=None)
|
self.private_api = FakeWebTabPrivate(tab=self, mode_manager=None)
|
||||||
wrapped = QWidget()
|
wrapped = QWidget()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
"""Test Zoom widget."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from qutebrowser.mainwindow.statusbar.zoom import Zoom
|
||||||
|
from typing import Any
|
||||||
|
import pytestqt.qtbot
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def zoom(qtbot: pytestqt.qtbot.QtBot, config_stub: Any) -> Zoom:
|
||||||
|
"""Fixture providing a Zoom widget."""
|
||||||
|
widget = Zoom()
|
||||||
|
qtbot.add_widget(widget)
|
||||||
|
return widget
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('factor, expected', [
|
||||||
|
(0.25, '[25%]'),
|
||||||
|
(0.5, '[50%]'),
|
||||||
|
(0.75, '[75%]'),
|
||||||
|
(1.5, '[150%]'),
|
||||||
|
(2, '[200%]'),
|
||||||
|
(3, '[300%]'),
|
||||||
|
(4, '[400%]'),
|
||||||
|
(5, '[500%]'),
|
||||||
|
])
|
||||||
|
@pytest.mark.parametrize("show", ["non-default", "always"])
|
||||||
|
def test_percentage_texts(zoom: Zoom, factor: float, show: str, expected: str,
|
||||||
|
config_stub: Any) -> None:
|
||||||
|
"""Test text displayed by the widget based on the zoom factor of a tab and a config value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
factor: zoom factor of the tab as a float.
|
||||||
|
show: config value for `statusbar.zoom.show`.
|
||||||
|
expected: expected text given factor.
|
||||||
|
"""
|
||||||
|
config_stub.val.statusbar.zoom.show = show
|
||||||
|
zoom.on_zoom_changed(factor=factor)
|
||||||
|
assert zoom.text() == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('show, expected', [
|
||||||
|
("always", '[100%]'),
|
||||||
|
("non-default", ''),
|
||||||
|
])
|
||||||
|
def test_default_percentage_text(zoom: Zoom, show: str, expected: str,
|
||||||
|
config_stub: Any) -> None:
|
||||||
|
"""Test default percentage text based on a config value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
show: config value for `statusbar.zoom.show`.
|
||||||
|
expected: expected text given show config value.
|
||||||
|
"""
|
||||||
|
config_stub.val.statusbar.zoom.show = show
|
||||||
|
zoom.on_zoom_changed(factor=1)
|
||||||
|
assert zoom.text() == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_tab_change(zoom: Zoom, fake_web_tab: Any) -> None:
|
||||||
|
"""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%]'
|
||||||
Loading…
Reference in New Issue