diff --git a/qutebrowser/browser/browsertab.py b/qutebrowser/browser/browsertab.py index dd3673aa6..aea15a257 100644 --- a/qutebrowser/browser/browsertab.py +++ b/qutebrowser/browser/browsertab.py @@ -114,6 +114,10 @@ class TabData: netrc_used = attr.ib(False) input_mode = attr.ib(usertypes.KeyMode.normal) + def should_show_icon(self): + return (config.val.tabs.favicons.show == 'always' or + config.val.tabs.favicons.show == 'pinned' and self.pinned) + class AbstractAction: diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py index d492eb513..f2438cebe 100644 --- a/qutebrowser/browser/commands.py +++ b/qutebrowser/browser/commands.py @@ -502,7 +502,7 @@ class CommandDispatcher: idx = new_tabbed_browser.widget.indexOf(newtab) new_tabbed_browser.widget.set_page_title(idx, cur_title) - if config.val.tabs.favicons.show: + if curtab.data.should_show_icon(): new_tabbed_browser.widget.setTabIcon(idx, curtab.icon()) if config.val.tabs.tabs_are_windows: new_tabbed_browser.widget.window().setWindowIcon(curtab.icon()) diff --git a/qutebrowser/config/configdata.yml b/qutebrowser/config/configdata.yml index 1de220938..556e4af33 100644 --- a/qutebrowser/config/configdata.yml +++ b/qutebrowser/config/configdata.yml @@ -1252,9 +1252,14 @@ tabs.favicons.scale: `tabs.padding`. tabs.favicons.show: - default: true - type: Bool - desc: Show favicons in the tab bar. + default: always + type: + name: String + valid_values: + - always: Always show favicons. + - never: Always hide favicons. + - pinned: Show favicons only on pinned tabs. + desc: When to show favicons in the tab bar. tabs.last_close: default: ignore diff --git a/qutebrowser/config/configfiles.py b/qutebrowser/config/configfiles.py index fdb1583e0..986ca3f56 100644 --- a/qutebrowser/config/configfiles.py +++ b/qutebrowser/config/configfiles.py @@ -268,6 +268,15 @@ class YamlConfig(QObject): del settings['bindings.default'] self._mark_changed() + # Option to show favicons only for pinned tabs changed the type of + # tabs.favicons.show from Bool to String + name = 'tabs.favicons.show' + if name in settings: + for scope, val in settings[name].items(): + if isinstance(val, bool): + settings[name][scope] = 'always' if val else 'never' + self._mark_changed() + return settings def _validate(self, settings): diff --git a/qutebrowser/mainwindow/tabbedbrowser.py b/qutebrowser/mainwindow/tabbedbrowser.py index cedb0cf33..ce36f0038 100644 --- a/qutebrowser/mainwindow/tabbedbrowser.py +++ b/qutebrowser/mainwindow/tabbedbrowser.py @@ -531,16 +531,8 @@ class TabbedBrowser(QWidget): def _update_favicons(self): """Update favicons when config was changed.""" - for i, tab in enumerate(self.widgets()): - if config.val.tabs.favicons.show: - self.widget.setTabIcon(i, tab.icon()) - if config.val.tabs.tabs_are_windows: - self.widget.window().setWindowIcon(tab.icon()) - else: - self.widget.setTabIcon(i, QIcon()) - if config.val.tabs.tabs_are_windows: - window = self.widget.window() - window.setWindowIcon(self.default_window_icon) + for tab in self.widgets(): + self.widget.update_tab_favicon(tab) @pyqtSlot() def on_load_started(self, tab): @@ -559,7 +551,7 @@ class TabbedBrowser(QWidget): tab.data.keep_icon = False else: if (config.val.tabs.tabs_are_windows and - config.val.tabs.favicons.show): + tab.data.should_show_icon()): self.widget.window().setWindowIcon(self.default_window_icon) if idx == self.widget.currentIndex(): self._update_window_title() @@ -623,7 +615,7 @@ class TabbedBrowser(QWidget): tab: The WebView where the title was changed. icon: The new icon """ - if not config.val.tabs.favicons.show: + if not tab.data.should_show_icon(): return try: idx = self._tab_index(tab) diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index a8cdcf54e..6a6eac901 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -108,6 +108,7 @@ class TabWidget(QTabWidget): bar.set_tab_data(idx, 'pinned', pinned) tab.data.pinned = pinned + self.update_tab_favicon(tab) self.update_tab_title(idx) def tab_indicator_color(self, idx): @@ -300,6 +301,19 @@ class TabWidget(QTabWidget): qtutils.ensure_valid(url) return url + def update_tab_favicon(self, tab: QWidget): + """Update favicon of the given tab.""" + idx = self.indexOf(tab) + + if tab.data.should_show_icon(): + self.setTabIcon(idx, tab.icon()) + if config.val.tabs.tabs_are_windows: + self.window().setWindowIcon(tab.icon()) + else: + self.setTabIcon(idx, QIcon()) + if config.val.tabs.tabs_are_windows: + self.window().setWindowIcon(self.window().windowIcon()) + class TabBar(QTabBar): @@ -906,7 +920,7 @@ class TabBarStyle(QCommonStyle): # reserve space for favicon when tab bar is vertical (issue #1968) position = config.val.tabs.position if (position in [QTabWidget.East, QTabWidget.West] and - config.val.tabs.favicons.show): + config.val.tabs.favicons.show != 'never'): tab_icon_size = icon_size else: actual_size = opt.icon.actualSize(icon_size, icon_mode, icon_state) diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py index ea7cbf268..edc81f139 100644 --- a/tests/helpers/stubs.py +++ b/tests/helpers/stubs.py @@ -266,6 +266,9 @@ class FakeWebTab(browsertab.AbstractTab): def shutdown(self): pass + def icon(self): + return self.windowIcon() + class FakeSignal: diff --git a/tests/unit/config/test_configfiles.py b/tests/unit/config/test_configfiles.py index 96f5d4976..13873d98e 100644 --- a/tests/unit/config/test_configfiles.py +++ b/tests/unit/config/test_configfiles.py @@ -233,6 +233,22 @@ class TestYaml: data = autoconfig.read() assert 'bindings.default' not in data + @pytest.mark.parametrize('show', + [True, False, 'always', 'never', 'pinned']) + def test_tabs_favicons_show(self, yaml, autoconfig, show): + """Tests for migration of tabs.favicons.show.""" + autoconfig.write({'tabs.favicons.show': {'global': show}}) + + yaml.load() + yaml._save() + + data = autoconfig.read() + if isinstance(show, bool): + when = 'always' if show else 'never' + else: + when = show + assert data['tabs.favicons.show']['global'] == when + def test_renamed_key_unknown_target(self, monkeypatch, yaml, autoconfig): """A key marked as renamed with invalid name should raise an error."""