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
|
||||
official qutebrowser support yet).
|
||||
- Support for hinting elements which are part of an (open) shadow DOM.
|
||||
- Show zoom percentage in statusbar. (#2870)
|
||||
|
||||
Changed
|
||||
~~~~~~~
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -728,8 +728,20 @@ class WebEngineZoom(browsertab.AbstractZoom):
|
|||
|
||||
_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):
|
||||
self._widget.setZoomFactor(factor)
|
||||
if not hasattr(self._widget.page(), "zoomFactorChanged"):
|
||||
self.factor_changed.emit(factor)
|
||||
|
||||
|
||||
class WebEngineElements(browsertab.AbstractElements):
|
||||
|
|
@ -1286,6 +1298,7 @@ class WebEngineTab(browsertab.AbstractTab):
|
|||
search: WebEngineSearch
|
||||
audio: WebEngineAudio
|
||||
printing: WebEnginePrinting
|
||||
zoom: WebEngineZoom
|
||||
|
||||
def __init__(self, *, win_id, mode_manager, private, parent=None):
|
||||
super().__init__(win_id=win_id,
|
||||
|
|
@ -1760,5 +1773,6 @@ class WebEngineTab(browsertab.AbstractTab):
|
|||
self.audio._connect_signals()
|
||||
self.search.connect_signals()
|
||||
self.printing.connect_signals()
|
||||
self.zoom.connect_signals()
|
||||
self._permissions.connect_signals()
|
||||
self._scripts.connect_signals()
|
||||
|
|
|
|||
|
|
@ -2208,10 +2208,21 @@ 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']
|
||||
default: ['keypress', 'search_match', 'url', 'zoom', 'scroll',
|
||||
'history', 'tabs', 'progress']
|
||||
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.background:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
@ -248,7 +252,7 @@ class StatusBar(QWidget):
|
|||
|
||||
if segment == 'scroll_raw':
|
||||
widget.set_raw()
|
||||
elif segment in ('history', 'progress'):
|
||||
elif segment in ('history', 'progress', 'zoom'):
|
||||
widget.enabled = True
|
||||
if tab:
|
||||
widget.on_tab_changed(tab)
|
||||
|
|
@ -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]
|
||||
|
|
@ -423,6 +428,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
|
||||
|
||||
|
|
|
|||
|
|
@ -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_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(
|
||||
|
|
|
|||
|
|
@ -205,6 +205,18 @@ class FakeWebTabScroller(browsertab.AbstractScroller):
|
|||
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):
|
||||
|
||||
"""Fake for Web{Kit,Engine}History."""
|
||||
|
|
@ -245,7 +257,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 +267,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()
|
||||
|
|
|
|||
|
|
@ -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