summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortoofar <toofar@spalge.com>2023-03-15 16:40:54 +1300
committertoofar <toofar@spalge.com>2023-03-15 17:07:31 +1300
commit0f01027570934821678b6a41a768480caa63b625 (patch)
tree18cb575400f3632ddc794365b7ef976cfbaf850b
parent30125a2e2e302b79a168db36cb5b3f18ff50f5bd (diff)
downloadqutebrowser-0f01027570934821678b6a41a768480caa63b625.tar.gz
qutebrowser-0f01027570934821678b6a41a768480caa63b625.zip
Override QTabBar text eilding
The fontMetrics().elidedText(...) call is copied from the base QTabBar implementation of initStyleOption(). But here we are calling it with a text_rect from our custom style class. In Qt6 QStyleSheetStyle no longer calls into our custom Style class for the SE_TabBarTabText SubElement so it ends up getting a text width from QCommonStyle which is wrong for vertical tabs (`QCommonStylePrivate::tabLayout()` seems to transpose the rect, maybe it thinks vertical tabs should have the text running vertically too). Also resolves the issue that when tabs.title.alignment is set to center the leftmost character or two of titles wouldn't be visible when tabs where small enough that the text got elided. Not 100% sure why but presumably it wasn't picking up the padding etc logic in our custom style class. In the test I don't test the exact elided text when we don't have much room because it might differ based on what monospace font is picked up in the tests. So the amount elided might change. Also in the not-elided one I'm only testing endswith() because the index should be at the start of the string which I don't really care about. Fixes: #7313 Fixes: #7205
-rw-r--r--qutebrowser/mainwindow/tabwidget.py26
-rw-r--r--tests/unit/mainwindow/test_tabwidget.py35
2 files changed, 59 insertions, 2 deletions
diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py
index 5e4f519fa..580da64b4 100644
--- a/qutebrowser/mainwindow/tabwidget.py
+++ b/qutebrowser/mainwindow/tabwidget.py
@@ -405,7 +405,8 @@ class TabBar(QTabBar):
def __init__(self, win_id, parent=None):
super().__init__(parent)
self._win_id = win_id
- self.setStyle(TabBarStyle())
+ self._our_style = TabBarStyle()
+ self.setStyle(self._our_style)
self.vertical = False
self._auto_hide_timer = QTimer()
self._auto_hide_timer.setSingleShot(True)
@@ -696,6 +697,29 @@ class TabBar(QTabBar):
qtutils.ensure_valid(size)
return size
+ def initStyleOption(self, opt, idx):
+ """Override QTabBar.initStyleOption().
+
+ Used to calculate styling clues from a widget for the GUI layer.
+ """
+ super().initStyleOption(opt, idx)
+
+ # Re-do the text elision that the base QTabBar does, but using a text
+ # rectangle computed by out TabBarStyle. With Qt6 the base class ends
+ # up using QCommonStyle directly for that which has a different opinon
+ # of how vertical tabs should work.
+ text_rect = self._our_style.subElementRect(
+ QStyle.SubElement.SE_TabBarTabText,
+ opt,
+ self,
+ )
+ opt.text = self.fontMetrics().elidedText(
+ self.tabText(idx),
+ self.elideMode(),
+ text_rect.width(),
+ Qt.TextFlag.TextShowMnemonic,
+ )
+
def paintEvent(self, event):
"""Override paintEvent to draw the tabs like we want to."""
p = QStylePainter(self)
diff --git a/tests/unit/mainwindow/test_tabwidget.py b/tests/unit/mainwindow/test_tabwidget.py
index db300d7a6..d6289dac6 100644
--- a/tests/unit/mainwindow/test_tabwidget.py
+++ b/tests/unit/mainwindow/test_tabwidget.py
@@ -23,8 +23,9 @@
import functools
import pytest
-from qutebrowser.qt.gui import QIcon, QPixmap
+from unittest.mock import Mock
+from qutebrowser.qt.gui import QIcon, QPixmap
from qutebrowser.mainwindow import tabwidget
from qutebrowser.utils import usertypes
@@ -71,6 +72,38 @@ class TestTabWidget:
assert first_size == widget.tabBar().tabSizeHint(i)
assert first_size_min == widget.tabBar().minimumTabSizeHint(i)
+ @pytest.fixture
+ def paint_spy(self, monkeypatch):
+ spy = Mock()
+ monkeypatch.setattr(tabwidget, "QStylePainter", spy)
+ return spy
+
+ def test_tab_text_edlided_for_narrow_tabs(self, paint_spy, widget, fake_web_tab):
+ """Make sure text gets elided for narrow tabs."""
+ widget.setMaximumWidth(100)
+ widget.addTab(fake_web_tab(), "one two three four")
+
+ fake_paint_event = Mock()
+ fake_paint_event.region.return_value.intersects.return_value = True
+ widget.tabBar().paintEvent(fake_paint_event)
+
+ style_opt = paint_spy.return_value.drawControl.call_args_list[0][0][1]
+ assert len(style_opt.text) < len(widget.tabBar().tabText(0))
+ assert style_opt.text.endswith("…")
+ assert len(style_opt.text) > len("…")
+
+ def test_tab_text_not_edlided_for_wide_tabs(self, paint_spy, widget, fake_web_tab):
+ """Make sure text doesn't get elided for wide tabs."""
+ widget.setMaximumWidth(200)
+ widget.addTab(fake_web_tab(), "one two three four")
+
+ fake_paint_event = Mock()
+ fake_paint_event.region.return_value.intersects.return_value = True
+ widget.tabBar().paintEvent(fake_paint_event)
+
+ style_opt = paint_spy.return_value.drawControl.call_args_list[0][0][1]
+ assert style_opt.text.endswith(widget.tabBar().tabText(0))
+
@pytest.mark.parametrize("shrink_pinned", [True, False])
@pytest.mark.parametrize("vertical", [True, False])
def test_pinned_size(self, widget, fake_web_tab, config_stub,