From 1bfbdd79e4e527248d615ab2f6ff42928183ff40 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 16 May 2014 14:20:37 +0200 Subject: [PATCH] Make scroll bars hideable --- TODO | 1 - qutebrowser/browser/curcommand.py | 19 +++++-- qutebrowser/config/_conftypes.py | 21 +++++++- qutebrowser/config/configdata.py | 8 +++ qutebrowser/widgets/_tabbedbrowser.py | 2 +- qutebrowser/widgets/statusbar/_percentage.py | 2 +- qutebrowser/widgets/webview.py | 52 ++++++++++++-------- 7 files changed, 75 insertions(+), 30 deletions(-) diff --git a/TODO b/TODO index a4a9d8f2e..9ccbb296b 100644 --- a/TODO +++ b/TODO @@ -86,7 +86,6 @@ Improvements / minor features QNetworkManager.setCache() and use a QNetworkDiskCache probably - clear cookies command - keybind/aliases should have completion for commands/arguments -- Hiding scrollbars - Ctrl+A/X to increase/decrease last number in URL - logging contexts - Add more element-selection-detection code (with options?) based on: diff --git a/qutebrowser/browser/curcommand.py b/qutebrowser/browser/curcommand.py index 2ad93181d..4b60ff9de 100644 --- a/qutebrowser/browser/curcommand.py +++ b/qutebrowser/browser/curcommand.py @@ -24,7 +24,7 @@ from tempfile import mkstemp from functools import partial from PyQt5.QtWidgets import QApplication -from PyQt5.QtCore import pyqtSlot, Qt, QObject, QProcess +from PyQt5.QtCore import pyqtSlot, Qt, QObject, QProcess, QPoint from PyQt5.QtGui import QClipboard from PyQt5.QtPrintSupport import QPrintDialog, QPrintPreviewDialog @@ -78,10 +78,19 @@ class CurCommandDispatcher(QObject): perc = float(perc) perc = utils.check_overflow(perc, 'int', fatal=False) frame = self._tabs.currentWidget().page_.currentFrame() - m = frame.scrollBarMaximum(orientation) - if m == 0: - return - frame.setScrollBarValue(orientation, int(m * perc / 100)) + if orientation == Qt.Horizontal: + right = frame.contentsSize().width() + viewsize = frame.geometry().width() + x = (right - viewsize) * perc / 100 + y = frame.scrollPosition().y() + elif orientation == Qt.Vertical: + bottom = frame.contentsSize().height() + viewsize = frame.geometry().height() + x = frame.scrollPosition().x() + y = (bottom - viewsize) * perc / 100 + else: + raise ValueError("Invalid orientation {}".format(orientation)) + frame.setScrollPosition(QPoint(x, y)) def _prevnext(self, prev, newtab): """Inner logic for {tab,}{prev,next}page.""" diff --git a/qutebrowser/config/_conftypes.py b/qutebrowser/config/_conftypes.py index 66548474f..81fef4e3a 100644 --- a/qutebrowser/config/_conftypes.py +++ b/qutebrowser/config/_conftypes.py @@ -22,7 +22,7 @@ import shlex import os.path from sre_constants import error as RegexError -from PyQt5.QtCore import QUrl +from PyQt5.QtCore import Qt, QUrl from PyQt5.QtGui import QColor from PyQt5.QtNetwork import QNetworkProxy @@ -650,6 +650,25 @@ class ZoomPerc(Perc): # FIXME we should validate the percentage is in the list here. +class ScrollBarPolicy(BaseType): + + """Base class for scroll bar policies.""" + + valid_values = ValidValues( + ('as-needed', "Show a scroll bar when the content is too large."), + ('always', "Always show a scroll bar."), + ('never', "Never show a scroll bar."), + ) + + def transform(self, value): + mapping = { + 'as-needed': Qt.ScrollBarAsNeeded, + 'always': Qt.ScrollBarAlwaysOn, + 'never': Qt.ScrollBarAlwaysOff, + } + return mapping[value] + + class HintMode(BaseType): """Base class for the hints -> mode setting.""" diff --git a/qutebrowser/config/configdata.py b/qutebrowser/config/configdata.py index 1c83512bb..c16715a7c 100644 --- a/qutebrowser/config/configdata.py +++ b/qutebrowser/config/configdata.py @@ -197,6 +197,14 @@ DATA = OrderedDict([ SettingValue(types.ShellCommand(placeholder=True), 'gvim -f "{}"'), "The editor (and arguments) to use for the open_editor binding. " "Use {} for the filename. Gets split via shutils."), + + ('show-scroll-bar-horizontal', + SettingValue(types.ScrollBarPolicy(), 'never'), + "Whether to show horizontal scrollbar for web content."), + + ('show-scroll-bar-vertical', + SettingValue(types.ScrollBarPolicy(), 'never'), + "Whether to show vertical scrollbar for web content."), )), ('network', sect.KeyValue( diff --git a/qutebrowser/widgets/_tabbedbrowser.py b/qutebrowser/widgets/_tabbedbrowser.py index 590fdda6f..adb2ddfbf 100644 --- a/qutebrowser/widgets/_tabbedbrowser.py +++ b/qutebrowser/widgets/_tabbedbrowser.py @@ -142,7 +142,7 @@ class TabbedBrowser(TabWidget): tab.loadStarted.connect(self._filter.create(self.cur_load_started)) tab.statusBarMessage.connect( self._filter.create(self.cur_statusbar_message)) - tab.scroll_pos_changed.connect( + tab.scroll_perc_changed.connect( self._filter.create(self.cur_scroll_perc_changed)) tab.url_text_changed.connect( self._filter.create(self.cur_url_text_changed)) diff --git a/qutebrowser/widgets/statusbar/_percentage.py b/qutebrowser/widgets/statusbar/_percentage.py index 424c797cd..b057d1aa8 100644 --- a/qutebrowser/widgets/statusbar/_percentage.py +++ b/qutebrowser/widgets/statusbar/_percentage.py @@ -50,4 +50,4 @@ class Percentage(TextBase): def on_tab_changed(self, idx): """Update scroll position when tab changed.""" tab = self.sender().widget(idx) - self.set_perc(*tab.scroll_pos) + self.set_perc(*tab.scroll_perc) diff --git a/qutebrowser/widgets/webview.py b/qutebrowser/widgets/webview.py index d8923be9c..f8760789f 100644 --- a/qutebrowser/widgets/webview.py +++ b/qutebrowser/widgets/webview.py @@ -54,14 +54,14 @@ class WebView(QWebView): We need this rather than signals to make createWindow work. progress: loading progress of this page. - scroll_pos: The current scroll position as (x%, y%) tuple. + scroll_perc: The current scroll position as (x%, y%) tuple. _url_text: The current URL as string. Accessed via url_text property. _load_status: loading status of this page (index into LoadStatus) Accessed via load_status property. _has_ssl_errors: Whether SSL errors occured during loading. _zoom: A NeighborList with the zoom levels. - _old_scroll_pos: The old scroll position. + _old_scroll_perc: The old scroll position. _shutdown_callback: Callback to be called after shutdown. _open_target: Where to open the next tab ("normal", "tab", "bgtab") _force_open_target: Override for _open_target. @@ -69,7 +69,7 @@ class WebView(QWebView): _destroyed: Dict of all items to be destroyed on shtudown. Signals: - scroll_pos_changed: Scroll percentage of current tab changed. + scroll_perc_changed: Scroll percentage of current tab changed. arg 1: x-position in %. arg 2: y-position in %. linkHovered: QWebPages linkHovered signal exposed. @@ -77,7 +77,7 @@ class WebView(QWebView): url_text_changed: Current URL string changed. """ - scroll_pos_changed = pyqtSignal(int, int) + scroll_perc_changed = pyqtSignal(int, int) linkHovered = pyqtSignal(str, str, str) load_status_changed = pyqtSignal(str) url_text_changed = pyqtSignal(str) @@ -86,8 +86,8 @@ class WebView(QWebView): super().__init__(parent) self._load_status = LoadStatus.none self.tabbedbrowser = parent - self.scroll_pos = (-1, -1) - self._old_scroll_pos = (-1, -1) + self.scroll_perc = (-1, -1) + self._old_scroll_perc = (-1, -1) self._shutdown_callback = None self._open_target = Target.normal self._force_open_target = None @@ -111,7 +111,10 @@ class WebView(QWebView): self.loadProgress.connect(lambda p: setattr(self, 'progress', p)) self.page_.networkAccessManager().sslErrors.connect( lambda *args: setattr(self, '_has_ssl_errors', True)) - # FIXME find some way to hide scrollbars without setScrollBarPolicy + self.page_.mainFrame().setScrollBarPolicy( + Qt.Horizontal, config.get('general', 'show-scroll-bar-horizontal')) + self.page_.mainFrame().setScrollBarPolicy( + Qt.Vertical, config.get('general', 'show-scroll-bar-vertical')) def __repr__(self): return "WebView(url='{}')".format( @@ -386,8 +389,17 @@ class WebView(QWebView): @pyqtSlot(str, str) def on_config_changed(self, section, option): """Update tab config when config was changed.""" - if section == 'general' and option in ['zoom-levels', 'default-zoom']: - self._init_neighborlist() + if section == 'general': + if option in ['zoom-levels', 'default-zoom']: + self._init_neighborlist() + elif option == 'show-scroll-bar-horizontal': + self.page_.mainFrame().setScrollBarPolicy( + Qt.Horizontal, + config.get('general', 'show-scroll-bar-horizontal')) + elif option == 'show-scroll-bar-vertical': + self.page_.mainFrame().setScrollBarPolicy( + Qt.Vertical, + config.get('general', 'show-scroll-bar-vertical')) @pyqtSlot('QMouseEvent') def on_mouse_event(self, evt): @@ -475,23 +487,21 @@ class WebView(QWebView): e: The QPaintEvent. Emit: - scroll_pos_changed; If the scroll position changed. + scroll_perc_changed; If the scroll position changed. Return: The superclass event return value. """ frame = self.page_.mainFrame() - new_pos = (frame.scrollBarValue(Qt.Horizontal), - frame.scrollBarValue(Qt.Vertical)) - if self._old_scroll_pos != new_pos: - self._old_scroll_pos = new_pos - logging.debug("Updating scroll position") - m = (frame.scrollBarMaximum(Qt.Horizontal), - frame.scrollBarMaximum(Qt.Vertical)) - perc = (round(100 * new_pos[0] / m[0]) if m[0] != 0 else 0, - round(100 * new_pos[1] / m[1]) if m[1] != 0 else 0) - self.scroll_pos = perc - self.scroll_pos_changed.emit(*perc) + new_pos = frame.scrollPosition() + if self._old_scroll_perc != new_pos: + self._old_scroll_perc = new_pos + max_x = frame.contentsSize().width() - frame.geometry().width() + max_y = frame.contentsSize().height() - frame.geometry().height() + perc = (round(100 * new_pos.x() / max_x) if max_x != 0 else 0, + round(100 * new_pos.y() / max_y) if max_y != 0 else 0) + self.scroll_perc = perc + self.scroll_perc_changed.emit(*perc) # Let superclass handle the event return super().paintEvent(e)