Fix various zooming issues
This commit is contained in:
parent
edb65ecf50
commit
16c397a9d2
@ -354,7 +354,7 @@ class CommandDispatcher:
|
||||
if config.get('tabs', 'tabs-are-windows'):
|
||||
new_tabbed_browser.window().setWindowIcon(curtab.icon())
|
||||
newtab.keep_icon = True
|
||||
newtab.set_zoom_factor(curtab.zoom_factor())
|
||||
newtab.zoom.set_factor(curtab.zoom.factor())
|
||||
newtab.history.deserialize(curtab.history.serialize())
|
||||
return newtab
|
||||
|
||||
@ -663,7 +663,7 @@ class CommandDispatcher:
|
||||
"""
|
||||
tab = self._current_widget()
|
||||
try:
|
||||
perc = tab.zoom(count)
|
||||
perc = tab.zoom.offset(count)
|
||||
except ValueError as e:
|
||||
raise cmdexc.CommandError(e)
|
||||
message.info(self._win_id, "Zoom level: {}%".format(perc))
|
||||
@ -678,7 +678,7 @@ class CommandDispatcher:
|
||||
"""
|
||||
tab = self._current_widget()
|
||||
try:
|
||||
perc = tab.zoom(-count)
|
||||
perc = tab.zoom.offset(-count)
|
||||
except ValueError as e:
|
||||
raise cmdexc.CommandError(e)
|
||||
message.info(self._win_id, "Zoom level: {}%".format(perc))
|
||||
@ -703,9 +703,9 @@ class CommandDispatcher:
|
||||
tab = self._current_widget()
|
||||
|
||||
try:
|
||||
tab.zoom_perc(level)
|
||||
except ValueError as e:
|
||||
raise cmdexc.CommandError(e)
|
||||
tab.zoom.set_factor(float(level) / 100)
|
||||
except ValueError:
|
||||
raise cmdexc.CommandError("Can't zoom {}%!".format(level))
|
||||
message.info(self._win_id, "Zoom level: {}%".format(level))
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||
|
@ -21,11 +21,12 @@
|
||||
|
||||
import itertools
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, QUrl, QObject
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject, QPoint
|
||||
from PyQt5.QtGui import QIcon
|
||||
from PyQt5.QtWidgets import QWidget, QLayout
|
||||
|
||||
from qutebrowser.utils import utils, objreg
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.utils import utils, objreg, usertypes
|
||||
|
||||
|
||||
tab_id_gen = itertools.count(0)
|
||||
@ -55,6 +56,94 @@ class WrapperLayout(QLayout):
|
||||
self._widget.setGeometry(r)
|
||||
|
||||
|
||||
class AbstractZoom(QObject):
|
||||
|
||||
"""Attribute of AbstractTab for controlling zoom.
|
||||
|
||||
Attributes:
|
||||
_neighborlist: A NeighborList with the zoom levels.
|
||||
_default_zoom_changed: Whether the zoom was changed from the default.
|
||||
"""
|
||||
|
||||
def __init__(self, win_id, parent=None):
|
||||
super().__init__(parent)
|
||||
self.widget = None
|
||||
self._win_id = win_id
|
||||
self._default_zoom_changed = False
|
||||
self._init_neighborlist()
|
||||
objreg.get('config').changed.connect(self.on_config_changed)
|
||||
|
||||
# # FIXME is this needed?
|
||||
# # For some reason, this signal doesn't get disconnected automatically
|
||||
# # when the WebView is destroyed on older PyQt versions.
|
||||
# # See https://github.com/The-Compiler/qutebrowser/issues/390
|
||||
# self.destroyed.connect(functools.partial(
|
||||
# cfg.changed.disconnect, self.init_neighborlist))
|
||||
|
||||
def _set_default_zoom(self):
|
||||
default_zoom = config.get('ui', 'default-zoom')
|
||||
self._set_factor_internal(float(default_zoom) / 100)
|
||||
|
||||
@pyqtSlot(str, str)
|
||||
def on_config_changed(self, section, option):
|
||||
if section == 'ui' and option in ('zoom-levels', 'default-zoom'):
|
||||
if not self._default_zoom_changed:
|
||||
factor = float(config.get('ui', 'default-zoom')) / 100
|
||||
self._set_factor_internal(factor)
|
||||
self._default_zoom_changed = False
|
||||
self._init_neighborlist()
|
||||
|
||||
def _init_neighborlist(self):
|
||||
"""Initialize self._neighborlist."""
|
||||
levels = config.get('ui', 'zoom-levels')
|
||||
self._neighborlist = usertypes.NeighborList(
|
||||
levels, mode=usertypes.NeighborList.Modes.edge)
|
||||
self._neighborlist.fuzzyval = config.get('ui', 'default-zoom')
|
||||
|
||||
def offset(self, offset):
|
||||
"""Increase/Decrease the zoom level by the given offset.
|
||||
|
||||
Args:
|
||||
offset: The offset in the zoom level list.
|
||||
|
||||
Return:
|
||||
The new zoom percentage.
|
||||
"""
|
||||
level = self._neighborlist.getitem(offset)
|
||||
self.set_factor(float(level) / 100, fuzzyval=False)
|
||||
return level
|
||||
|
||||
def set_factor(self, factor, *, fuzzyval=True):
|
||||
"""Zoom to a given zoom factor.
|
||||
|
||||
Args:
|
||||
factor: The zoom factor as float.
|
||||
fuzzyval: Whether to set the NeighborLists fuzzyval.
|
||||
"""
|
||||
if fuzzyval:
|
||||
self._neighborlist.fuzzyval = int(factor * 100)
|
||||
if factor < 0:
|
||||
raise ValueError("Can't zoom to factor {}!".format(factor))
|
||||
self._default_zoom_changed = True
|
||||
self._set_factor_internal(factor)
|
||||
|
||||
def factor(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@pyqtSlot(QPoint)
|
||||
def on_mouse_wheel_zoom(self, delta):
|
||||
"""Handle zooming via mousewheel requested by the web view."""
|
||||
divider = config.get('input', 'mouse-zoom-divider')
|
||||
factor = self.zoomFactor() + delta.y() / divider
|
||||
if factor < 0:
|
||||
return
|
||||
perc = int(100 * factor)
|
||||
message.info(self.win_id, "Zoom level: {}%".format(perc))
|
||||
self._neighborlist.fuzzyval = perc
|
||||
self._set_factor_internal(factor)
|
||||
self._default_zoom_changed = True
|
||||
|
||||
|
||||
class AbstractCaret(QObject):
|
||||
|
||||
"""Attribute of AbstractTab for caret browsing."""
|
||||
@ -262,6 +351,7 @@ class AbstractTab(QWidget):
|
||||
# self.history = AbstractHistory(self)
|
||||
# self.scroll = AbstractScroller(parent=self)
|
||||
# self.caret = AbstractCaret(win_id=win_id, tab=self, parent=self)
|
||||
# self.zoom = AbstractZoom(win_id=win_id)
|
||||
self._layout = None
|
||||
self._widget = None
|
||||
self.keep_icon = False # FIXME:refactor get rid of this?
|
||||
@ -272,6 +362,8 @@ class AbstractTab(QWidget):
|
||||
self.history.history = widget.history()
|
||||
self.scroll.widget = widget
|
||||
self.caret.widget = widget
|
||||
self.zoom.widget = widget
|
||||
widget.mouse_wheel_zoom.connect(self.zoom.on_mouse_wheel_zoom)
|
||||
widget.setParent(self)
|
||||
|
||||
@property
|
||||
@ -317,12 +409,6 @@ class AbstractTab(QWidget):
|
||||
def title(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def set_zoom_factor(self, factor):
|
||||
raise NotImplementedError
|
||||
|
||||
def zoom_factor(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def icon(self):
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -76,6 +76,15 @@ class WebEngineHistory(tab.AbstractHistory):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class WebEngineZoom(tab.AbstractZoom):
|
||||
|
||||
def _set_factor_internal(self, factor):
|
||||
self.widget.setZoomFactor(factor)
|
||||
|
||||
def factor(self):
|
||||
return self.widget.zoomFactor()
|
||||
|
||||
|
||||
class WebEngineViewTab(tab.AbstractTab):
|
||||
|
||||
def __init__(self, win_id, parent=None):
|
||||
@ -84,6 +93,7 @@ class WebEngineViewTab(tab.AbstractTab):
|
||||
self.history = WebEngineHistory(self)
|
||||
self.scroll = WebEngineScroller()
|
||||
self.caret = WebEngineCaret(win_id=win_id, tab=self, parent=self)
|
||||
self.zoom = WebEngineZoom(win_id=win_id, parent=self)
|
||||
self._set_widget(widget)
|
||||
self._connect_signals()
|
||||
|
||||
@ -102,12 +112,6 @@ class WebEngineViewTab(tab.AbstractTab):
|
||||
def load_status(self):
|
||||
return usertypes.LoadStatus.success
|
||||
|
||||
def set_zoom_factor(self, factor):
|
||||
self._widget.setZoomFactor(factor)
|
||||
|
||||
def zoom_factor(self):
|
||||
return self._widget.zoomFactor()
|
||||
|
||||
def dump_async(self, callback, *, plain=False):
|
||||
if plain:
|
||||
self._widget.page().toPlainText(callback)
|
||||
|
@ -213,6 +213,15 @@ class WebViewCaret(tab.AbstractCaret):
|
||||
self.widget.triggerPageAction(QWebPage.MoveToNextChar)
|
||||
|
||||
|
||||
class WebViewZoom(tab.AbstractZoom):
|
||||
|
||||
def _set_factor_internal(self, factor):
|
||||
self.widget.setZoomFactor(factor)
|
||||
|
||||
def factor(self):
|
||||
return self.widget.zoomFactor()
|
||||
|
||||
|
||||
class WebViewScroller(tab.AbstractScroller):
|
||||
|
||||
def pos_px(self):
|
||||
@ -338,7 +347,7 @@ class WebViewHistory(tab.AbstractHistory):
|
||||
cur_data = self.history.currentItem().userData()
|
||||
if cur_data is not None:
|
||||
if 'zoom' in cur_data:
|
||||
self.tab.zoom_perc(cur_data['zoom'] * 100)
|
||||
self.tab.zoom.set_factor(cur_data['zoom'])
|
||||
if ('scroll-pos' in cur_data and
|
||||
self.tab.scroll.pos_px() == QPoint(0, 0)):
|
||||
QTimer.singleShot(0, functools.partial(
|
||||
@ -349,12 +358,14 @@ class WebViewTab(tab.AbstractTab):
|
||||
|
||||
def __init__(self, win_id, parent=None):
|
||||
super().__init__(win_id)
|
||||
widget = webview.WebView(win_id, self.tab_id)
|
||||
widget = webview.WebView(win_id, self.tab_id, tab=self)
|
||||
self.history = WebViewHistory(self)
|
||||
self.scroll = WebViewScroller(parent=self)
|
||||
self.caret = WebViewCaret(win_id=win_id, tab=self, parent=self)
|
||||
self.zoom = WebViewZoom(win_id=win_id, parent=self)
|
||||
self._set_widget(widget)
|
||||
self._connect_signals()
|
||||
self.zoom._set_default_zoom()
|
||||
|
||||
def openurl(self, url):
|
||||
self._widget.openurl(url)
|
||||
@ -402,12 +413,6 @@ class WebViewTab(tab.AbstractTab):
|
||||
def title(self):
|
||||
return self._widget.title()
|
||||
|
||||
def set_zoom_factor(self, factor):
|
||||
self._widget.setZoomFactor(factor)
|
||||
|
||||
def zoom_factor(self):
|
||||
return self._widget.zoomFactor()
|
||||
|
||||
def has_selection(self):
|
||||
return self._widget.hasSelection()
|
||||
|
||||
|
@ -419,7 +419,7 @@ class BrowserPage(QWebPage):
|
||||
if data is None:
|
||||
return
|
||||
if 'zoom' in data:
|
||||
frame.page().view().zoom_perc(data['zoom'] * 100)
|
||||
frame.page().view().tab.zoom.set_factor(data['zoom'])
|
||||
if 'scroll-pos' in data and frame.scrollPosition() == QPoint(0, 0):
|
||||
frame.setScrollPosition(data['scroll-pos'])
|
||||
|
||||
|
@ -23,7 +23,7 @@ import sys
|
||||
import itertools
|
||||
import functools
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QTimer, QUrl
|
||||
from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QTimer, QUrl, QPoint
|
||||
from PyQt5.QtGui import QPalette
|
||||
from PyQt5.QtWidgets import QApplication, QStyleFactory
|
||||
from PyQt5.QtWebKit import QWebSettings
|
||||
@ -43,6 +43,7 @@ class WebView(QWebView):
|
||||
Our own subclass of a QWebView with some added bells and whistles.
|
||||
|
||||
Attributes:
|
||||
tab: The WebKitTab object for this WebView
|
||||
hintmanager: The HintManager instance for this view.
|
||||
progress: loading progress of this page.
|
||||
scroll_pos: The current scroll position as (x%, y%) tuple.
|
||||
@ -57,11 +58,9 @@ class WebView(QWebView):
|
||||
search_flags: The search flags of the last search.
|
||||
_tab_id: The tab ID of the view.
|
||||
_has_ssl_errors: Whether SSL errors occurred during loading.
|
||||
_zoom: A NeighborList with the zoom levels.
|
||||
_old_scroll_pos: The old scroll position.
|
||||
_check_insertmode: If True, in mouseReleaseEvent we should check if we
|
||||
need to enter/leave insert mode.
|
||||
_default_zoom_changed: Whether the zoom was changed from the default.
|
||||
_ignore_wheel_event: Ignore the next wheel event.
|
||||
See https://github.com/The-Compiler/qutebrowser/issues/395
|
||||
|
||||
@ -72,6 +71,9 @@ class WebView(QWebView):
|
||||
linkHovered: QWebPages linkHovered signal exposed.
|
||||
load_status_changed: The loading status changed
|
||||
url_text_changed: Current URL string changed.
|
||||
mouse_wheel_zoom: Emitted when the page should be zoomed because the
|
||||
mousewheel was used with ctrl.
|
||||
arg 1: The angle delta of the wheel event (QPoint)
|
||||
shutting_down: Emitted when the view is shutting down.
|
||||
"""
|
||||
|
||||
@ -80,13 +82,15 @@ class WebView(QWebView):
|
||||
load_status_changed = pyqtSignal(str)
|
||||
url_text_changed = pyqtSignal(str)
|
||||
shutting_down = pyqtSignal()
|
||||
mouse_wheel_zoom = pyqtSignal(QPoint)
|
||||
|
||||
def __init__(self, win_id, tab_id, parent=None):
|
||||
def __init__(self, win_id, tab_id, tab, parent=None):
|
||||
super().__init__(parent)
|
||||
if sys.platform == 'darwin' and qtutils.version_check('5.4'):
|
||||
# WORKAROUND for https://bugreports.qt.io/browse/QTBUG-42948
|
||||
# See https://github.com/The-Compiler/qutebrowser/issues/462
|
||||
self.setStyle(QStyleFactory.create('Fusion'))
|
||||
self.tab = tab
|
||||
self.win_id = win_id
|
||||
self.load_status = usertypes.LoadStatus.none
|
||||
self._check_insertmode = False
|
||||
@ -94,21 +98,12 @@ class WebView(QWebView):
|
||||
self.scroll_pos = (-1, -1)
|
||||
self.statusbar_message = ''
|
||||
self._old_scroll_pos = (-1, -1)
|
||||
self._zoom = None
|
||||
self._has_ssl_errors = False
|
||||
self._ignore_wheel_event = False
|
||||
self.keep_icon = False
|
||||
self.search_text = None
|
||||
self.search_flags = 0
|
||||
self.init_neighborlist()
|
||||
self._set_bg_color()
|
||||
cfg = objreg.get('config')
|
||||
cfg.changed.connect(self.init_neighborlist)
|
||||
# For some reason, this signal doesn't get disconnected automatically
|
||||
# when the WebView is destroyed on older PyQt versions.
|
||||
# See https://github.com/The-Compiler/qutebrowser/issues/390
|
||||
self.destroyed.connect(functools.partial(
|
||||
cfg.changed.disconnect, self.init_neighborlist))
|
||||
self.cur_url = QUrl()
|
||||
self.progress = 0
|
||||
self.registry = objreg.ObjectRegistry()
|
||||
@ -129,8 +124,6 @@ class WebView(QWebView):
|
||||
mode_manager.entered.connect(self.on_mode_entered)
|
||||
mode_manager.left.connect(self.on_mode_left)
|
||||
self.viewing_source = False
|
||||
self.setZoomFactor(float(config.get('ui', 'default-zoom')) / 100)
|
||||
self._default_zoom_changed = False
|
||||
if config.get('input', 'rocker-gestures'):
|
||||
self.setContextMenuPolicy(Qt.PreventContextMenu)
|
||||
self.urlChanged.connect(self.on_url_changed)
|
||||
@ -201,14 +194,8 @@ class WebView(QWebView):
|
||||
|
||||
@pyqtSlot(str, str)
|
||||
def on_config_changed(self, section, option):
|
||||
"""Reinitialize the zoom neighborlist if related config changed."""
|
||||
if section == 'ui' and option in ('zoom-levels', 'default-zoom'):
|
||||
if not self._default_zoom_changed:
|
||||
self.setZoomFactor(float(config.get('ui', 'default-zoom')) /
|
||||
100)
|
||||
self._default_zoom_changed = False
|
||||
self.init_neighborlist()
|
||||
elif section == 'input' and option == 'rocker-gestures':
|
||||
"""Update rocker gestures/background color."""
|
||||
if section == 'input' and option == 'rocker-gestures':
|
||||
if config.get('input', 'rocker-gestures'):
|
||||
self.setContextMenuPolicy(Qt.PreventContextMenu)
|
||||
else:
|
||||
@ -216,13 +203,6 @@ class WebView(QWebView):
|
||||
elif section == 'colors' and option == 'webpage.bg':
|
||||
self._set_bg_color()
|
||||
|
||||
def init_neighborlist(self):
|
||||
"""Initialize the _zoom neighborlist."""
|
||||
levels = config.get('ui', 'zoom-levels')
|
||||
self._zoom = usertypes.NeighborList(
|
||||
levels, mode=usertypes.NeighborList.Modes.edge)
|
||||
self._zoom.fuzzyval = config.get('ui', 'default-zoom')
|
||||
|
||||
def _mousepress_backforward(self, e):
|
||||
"""Handle back/forward mouse button presses.
|
||||
|
||||
@ -372,33 +352,6 @@ class WebView(QWebView):
|
||||
bridge = objreg.get('js-bridge')
|
||||
frame.addToJavaScriptWindowObject('qute', bridge)
|
||||
|
||||
def zoom_perc(self, perc, fuzzyval=True):
|
||||
"""Zoom to a given zoom percentage.
|
||||
|
||||
Args:
|
||||
perc: The zoom percentage as int.
|
||||
fuzzyval: Whether to set the NeighborLists fuzzyval.
|
||||
"""
|
||||
if fuzzyval:
|
||||
self._zoom.fuzzyval = int(perc)
|
||||
if perc < 0:
|
||||
raise ValueError("Can't zoom {}%!".format(perc))
|
||||
self.setZoomFactor(float(perc) / 100)
|
||||
self._default_zoom_changed = True
|
||||
|
||||
def zoom(self, offset):
|
||||
"""Increase/Decrease the zoom level.
|
||||
|
||||
Args:
|
||||
offset: The offset in the zoom level list.
|
||||
|
||||
Return:
|
||||
The new zoom percentage.
|
||||
"""
|
||||
level = self._zoom.getitem(offset)
|
||||
self.zoom_perc(level, fuzzyval=False)
|
||||
return level
|
||||
|
||||
@pyqtSlot('QUrl')
|
||||
def on_url_changed(self, url):
|
||||
"""Update cur_url when URL has changed.
|
||||
@ -635,14 +588,6 @@ class WebView(QWebView):
|
||||
return
|
||||
if e.modifiers() & Qt.ControlModifier:
|
||||
e.accept()
|
||||
divider = config.get('input', 'mouse-zoom-divider')
|
||||
factor = self.zoomFactor() + e.angleDelta().y() / divider
|
||||
if factor < 0:
|
||||
return
|
||||
perc = int(100 * factor)
|
||||
message.info(self.win_id, "Zoom level: {}%".format(perc))
|
||||
self._zoom.fuzzyval = perc
|
||||
self.setZoomFactor(factor)
|
||||
self._default_zoom_changed = True
|
||||
self.mouse_wheel_zoom.emit(e.angleDelta())
|
||||
else:
|
||||
super().wheelEvent(e)
|
||||
|
@ -166,7 +166,7 @@ class SessionManager(QObject):
|
||||
user_data = item.userData()
|
||||
if tab.history.current_idx() == idx:
|
||||
pos = tab.scroll.pos_px()
|
||||
item_data['zoom'] = tab.zoom_factor()
|
||||
item_data['zoom'] = tab.zoom.factor()
|
||||
item_data['scroll-pos'] = {'x': pos.x(), 'y': pos.y()}
|
||||
elif user_data is not None:
|
||||
if 'zoom' in user_data:
|
||||
|
Loading…
Reference in New Issue
Block a user