From b3a9e09d6cc42675416f62e27a063569b90e760d Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 18 Jun 2017 15:04:14 +0200 Subject: [PATCH] Add statusline widget for back/forward indicator Fixes https://github.com/qutebrowser/qutebrowser/issues/2737. --- qutebrowser/mainwindow/mainwindow.py | 2 + .../mainwindow/statusbar/backforward.py | 41 +++++++++++++ qutebrowser/mainwindow/statusbar/bar.py | 8 ++- scripts/dev/check_coverage.py | 2 + tests/helpers/stubs.py | 21 ++++++- .../mainwindow/statusbar/test_backforward.py | 57 +++++++++++++++++++ 6 files changed, 128 insertions(+), 3 deletions(-) create mode 100644 qutebrowser/mainwindow/statusbar/backforward.py create mode 100644 tests/unit/mainwindow/statusbar/test_backforward.py diff --git a/qutebrowser/mainwindow/mainwindow.py b/qutebrowser/mainwindow/mainwindow.py index 2f43ba58e..3a7d78e97 100644 --- a/qutebrowser/mainwindow/mainwindow.py +++ b/qutebrowser/mainwindow/mainwindow.py @@ -473,6 +473,8 @@ class MainWindow(QWidget): tabs.tab_index_changed.connect(status.tabindex.on_tab_index_changed) tabs.cur_url_changed.connect(status.url.set_url) + tabs.cur_url_changed.connect(functools.partial( + status.backforward.on_tab_cur_url_changed, tabs=tabs)) tabs.cur_link_hovered.connect(status.url.set_hover_url) tabs.cur_load_status_changed.connect(status.url.on_load_status_changed) tabs.cur_fullscreen_requested.connect(self._on_fullscreen_requested) diff --git a/qutebrowser/mainwindow/statusbar/backforward.py b/qutebrowser/mainwindow/statusbar/backforward.py new file mode 100644 index 000000000..a58373122 --- /dev/null +++ b/qutebrowser/mainwindow/statusbar/backforward.py @@ -0,0 +1,41 @@ +# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: + +# Copyright 2017 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + +"""Navigation (back/forward) indicator displayed in the statusbar.""" + +from qutebrowser.mainwindow.statusbar import textbase + + +class Backforward(textbase.TextBase): + + """Shows navigation indicator (if you can go backward and/or forward).""" + + def on_tab_cur_url_changed(self, tabs): + """Called on URL changes.""" + tab = tabs.currentWidget() + if tab is None: # pragma: no cover + return + text = '' + if tab.history.can_go_back(): + text += '<' + if tab.history.can_go_forward(): + text += '>' + if text: + text = '[' + text + ']' + self.setText(text) diff --git a/qutebrowser/mainwindow/statusbar/bar.py b/qutebrowser/mainwindow/statusbar/bar.py index ee3665ce2..64a084327 100644 --- a/qutebrowser/mainwindow/statusbar/bar.py +++ b/qutebrowser/mainwindow/statusbar/bar.py @@ -25,8 +25,9 @@ from PyQt5.QtWidgets import QWidget, QHBoxLayout, QStackedLayout, QSizePolicy from qutebrowser.browser import browsertab from qutebrowser.config import config, style from qutebrowser.utils import usertypes, log, objreg, utils -from qutebrowser.mainwindow.statusbar import (command, progress, keystring, - percentage, url, tabindex) +from qutebrowser.mainwindow.statusbar import (backforward, command, progress, + keystring, percentage, url, + tabindex) from qutebrowser.mainwindow.statusbar import text as textwidget @@ -184,6 +185,9 @@ class StatusBar(QWidget): self.percentage = percentage.Percentage() self._hbox.addWidget(self.percentage) + self.backforward = backforward.Backforward() + self._hbox.addWidget(self.backforward) + self.tabindex = tabindex.TabIndex() self._hbox.addWidget(self.tabindex) diff --git a/scripts/dev/check_coverage.py b/scripts/dev/check_coverage.py index 7e5a2d47a..b03fb7ef4 100644 --- a/scripts/dev/check_coverage.py +++ b/scripts/dev/check_coverage.py @@ -117,6 +117,8 @@ PERFECT_FILES = [ 'mainwindow/statusbar/textbase.py'), ('tests/unit/mainwindow/statusbar/test_url.py', 'mainwindow/statusbar/url.py'), + ('tests/unit/mainwindow/statusbar/test_backforward.py', + 'mainwindow/statusbar/backforward.py'), ('tests/unit/mainwindow/test_messageview.py', 'mainwindow/messageview.py'), diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py index 0551f5a86..99cfbf01e 100644 --- a/tests/helpers/stubs.py +++ b/tests/helpers/stubs.py @@ -222,6 +222,23 @@ class FakeWebTabScroller(browsertab.AbstractScroller): return self._pos_perc +class FakeWebTabHistory(browsertab.AbstractHistory): + """Fake for Web{Kit,Engine}History.""" + + def __init__(self, tab, *, can_go_back, can_go_forward): + super().__init__(tab) + self._can_go_back = can_go_back + self._can_go_forward = can_go_forward + + def can_go_back(self): + assert self._can_go_back is not None + return self._can_go_back + + def can_go_forward(self): + assert self._can_go_forward is not None + return self._can_go_forward + + class FakeWebTab(browsertab.AbstractTab): """Fake AbstractTab to use in tests.""" @@ -229,12 +246,14 @@ class FakeWebTab(browsertab.AbstractTab): def __init__(self, url=FakeUrl(), title='', tab_id=0, *, scroll_pos_perc=(0, 0), load_status=usertypes.LoadStatus.success, - progress=0): + progress=0, can_go_back=None, can_go_forward=None): super().__init__(win_id=0, mode_manager=None, private=False) self._load_status = load_status self._title = title self._url = url self._progress = progress + self.history = FakeWebTabHistory(self, can_go_back=can_go_back, + can_go_forward=can_go_forward) self.scroller = FakeWebTabScroller(self, scroll_pos_perc) wrapped = QWidget() self._layout.wrap(self, wrapped) diff --git a/tests/unit/mainwindow/statusbar/test_backforward.py b/tests/unit/mainwindow/statusbar/test_backforward.py new file mode 100644 index 000000000..e29d592b2 --- /dev/null +++ b/tests/unit/mainwindow/statusbar/test_backforward.py @@ -0,0 +1,57 @@ +# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: + +# Copyright 2017 Florian Bruhin (The Compiler) +# +# This file is part of qutebrowser. +# +# qutebrowser is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# qutebrowser is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with qutebrowser. If not, see . + + +"""Test Progress widget.""" + +import pytest + +from qutebrowser.mainwindow.statusbar import backforward + + +@pytest.fixture +def backforward_widget(qtbot): + widget = backforward.Backforward() + qtbot.add_widget(widget) + return widget + + +@pytest.mark.parametrize('can_go_back, can_go_forward, expected_text', [ + (False, False, ''), + (True, False, '[<]'), + (False, True, '[>]'), + (True, True, '[<>]'), +]) +def test_backforward_widget(backforward_widget, stubs, + fake_web_tab, can_go_back, can_go_forward, + expected_text): + """Ensure the Backforward widget shows the correct text.""" + tab = fake_web_tab(can_go_back=can_go_back, can_go_forward=can_go_forward) + tabbed_browser = stubs.TabbedBrowserStub() + tabbed_browser.current_index = 1 + tabbed_browser.tabs = [tab] + backforward_widget.on_tab_cur_url_changed(tabbed_browser) + assert backforward_widget.text() == expected_text + + # Check that the widget gets reset if empty. + if can_go_back and can_go_forward: + tab = fake_web_tab(can_go_back=False, can_go_forward=False) + tabbed_browser.tabs = [tab] + backforward_widget.on_tab_cur_url_changed(tabbed_browser) + assert backforward_widget.text() == ''