New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] add statusline widget for back/forward indicator #2738
Conversation
"""Shows navigation indicator (if you can go backward and/or forward).""" | ||
|
||
def on_tab_changed(self, tab): | ||
self.tab = tab |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely happy with saving the tab here, but it's a bit of a tricky situation - what about connecting the signal above like tabs.cur_url_changed.connect(functools.partial(status.backforward.on_url_changed, tabs=tabs))
, then taking a tabs
in on_url_changed
, and use tabs.currentWidget()
to get the current tab? I haven't tested it, but I think it should work and it seems less error-prone to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to work well.
@@ -0,0 +1,42 @@ | |||
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et: | |||
|
|||
# Copyright 2015-2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: 2017 instead of 2015-2017
I've also added the |
Any pointer for the tests? |
|
||
"""Shows navigation indicator (if you can go backward and/or forward).""" | ||
|
||
@pyqtSlot() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pyqtSlot()
on methods connected to PyQt signals is usually used because it has a memory/performance benefit (and also works around some bugs in older PyQt versions).
Here you're connecting a functools.partial
object however, and never connect to the method directly - so I'd rather remove it.
Yeah, a new file there sounds good. When it has 100% coverage, please also add it to As for mocking In 994e8c6 I just did some changes related to that as I discovered there were various other |
Just as a heads-up: I'm scheduled to have a (planned) eye surgery, so I probably won't respond to this anymore until somewhen next week. |
@The-Compiler |
What do you think about having some additional indicator on how far you can go forward/backwards, e.g. the number if it is |
Dunno. It doesn't sound too useful I think, and it's not very intuitive what it'd mean. Either way, I don't think you can get this information easily with the API we get from QtWebKit/QtWebEngine. |
Any update, @blueyed? |
No, I am using this myself, but otherwise I have to find the time to finish this, i.e. write the tests. |
I felt like writing some tests, so here they are: From b6cd620a8635aad1cec325e9ef3cbfd15bec1766 Mon Sep 17 00:00:00 2001
From: Florian Bruhin <git@the-compiler.org>
Date: Wed, 5 Jul 2017 15:45:23 +0200
Subject: [PATCH 4/4] Add statusbar.backforward tests
---
scripts/dev/check_coverage.py | 2 +
tests/helpers/stubs.py | 20 ++++++++-
.../unit/mainwindow/statusbar/test_backforward.py | 50 ++++++++++++++++++++++
3 files changed, 71 insertions(+), 1 deletion(-)
create mode 100644 tests/unit/mainwindow/statusbar/test_backforward.py
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..788d3ace3 100644
--- a/tests/helpers/stubs.py
+++ b/tests/helpers/stubs.py
@@ -222,6 +222,22 @@ class FakeWebTabScroller(browsertab.AbstractScroller):
return self._pos_perc
+class FakeWebTabHistory(browsertab.AbstractHistory):
+
+ 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 +245,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..15de7442f
--- /dev/null
+++ b/tests/unit/mainwindow/statusbar/test_backforward.py
@@ -0,0 +1,50 @@
+# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
+
+# Copyright 2017 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+
+"""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_url_changed(tabbed_browser)
+ assert backforward_widget.text() == expected_text
--
2.13.2
I'll also add some more line comments. |
|
||
"""Shows navigation indicator (if you can go backward and/or forward).""" | ||
|
||
def on_url_changed(self, tabs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit confusing still calling this on_url_changed
I think - maybe a simple update_text
or so would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is still called through tabs.cur_url_changed
?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but if something is called on_url_changed
, I'd expect it to be directly connected to a url_changed
signal and get a QUrl
as argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on_tab_cur_url_changed
then maybe?
I think it is better to have some explicit name, instead of update_text
?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me 😉
|
||
def on_url_changed(self, tabs): | ||
"""Called on URL changes.""" | ||
tab = tabs.currentWidget() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On Travis looks like this was invoked while tabs.currentWidget()
was None
and caused it to raise. I'm not 100% sure why it happened, but I think it'd be a good idea to add a:
if tab is None:
return
text += '<' | ||
if tab.history.can_go_forward(): | ||
text += '>' | ||
self.setText(text) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add []
around the text so it fits in with the other statusbar widgets?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It takes away some more space then, and IIRC the current behavior is what you see in Vimperator, too - but I will change it.
qutebrowser/mainwindow/mainwindow.py
Outdated
@@ -469,6 +469,7 @@ def _connect_signals(self): | |||
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_url_changed, tabs=tabs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please break this after the partial(
or so.
|
||
"""Navigation (back/forward) indicator displayed in the statusbar.""" | ||
|
||
from PyQt5.QtCore import pyqtSlot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused import
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is F401 (this error) in .flake8
? (since the beginning in 91e6f4c)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it's already checked by pylint and I don't want to do ignores twice everywhere for imports which aren't actually unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because pylint takes care of that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand what you're asking? Yes, pylint shows an unused import error, see my link above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, pylint does, but I was using only flake8 in the editor (which I will change for the project).
I think I answered my own question: F401 from flake8 is ignored, since pylint is supposed to lint this part.
@The-Compiler Remaining: the renaming of the hook. |
Why does Travis not run the PR? |
Good question... let me try to close and reopen it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with squashing things, yeah.
tests/helpers/stubs.py
Outdated
@@ -222,19 +222,37 @@ def pos_perc(self): | |||
return self._pos_perc | |||
|
|||
|
|||
class FakeWebTabHistory(browsertab.AbstractHistory): | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad, but this needs a docstring (something like """Fake for Web{Kit,Engine}History."""
or so)
def on_url_changed(self, tabs): | ||
"""Called on URL changes.""" | ||
tab = tabs.currentWidget() | ||
if tab is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, probably needs a # pragma: no cover
as it doesn't always happen.
Thanks! |
You're welcome! |
Fixes #2737.
TODO:
This change is