Merge remote-tracking branch 'origin/pr/3122'
This commit is contained in:
commit
e9483bc485
@ -336,7 +336,7 @@ class TabBar(QTabBar):
|
||||
return self.parent().currentWidget()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def _on_config_changed(self, option):
|
||||
def _on_config_changed(self, option: str):
|
||||
if option == 'fonts.tabs':
|
||||
self._set_font()
|
||||
elif option == 'tabs.favicons.scale':
|
||||
@ -351,6 +351,12 @@ class TabBar(QTabBar):
|
||||
if option.startswith('colors.tabs.'):
|
||||
self.update()
|
||||
|
||||
# Clear _minimum_tab_size_hint_helper cache when appropriate
|
||||
if option in ["tabs.indicator_padding",
|
||||
"tabs.padding",
|
||||
"tabs.width.indicator"]:
|
||||
self._minimum_tab_size_hint_helper.cache_clear()
|
||||
|
||||
def _on_show_switching_delay_changed(self):
|
||||
"""Set timer interval when tabs.show_switching_delay got changed."""
|
||||
self._auto_hide_timer.setInterval(config.val.tabs.show_switching_delay)
|
||||
@ -459,7 +465,7 @@ class TabBar(QTabBar):
|
||||
return
|
||||
super().mousePressEvent(e)
|
||||
|
||||
def minimumTabSizeHint(self, index, ellipsis: bool = True):
|
||||
def minimumTabSizeHint(self, index, ellipsis: bool = True) -> QSize:
|
||||
"""Set the minimum tab size to indicator/icon/... text.
|
||||
|
||||
Args:
|
||||
@ -469,38 +475,47 @@ class TabBar(QTabBar):
|
||||
Return:
|
||||
A QSize of the smallest tab size we can make.
|
||||
"""
|
||||
text = '\u2026' if ellipsis else self.tabText(index)
|
||||
icon = self.tabIcon(index)
|
||||
extent = self.style().pixelMetric(QStyle.PM_TabBarIconSize, None, self)
|
||||
if icon.isNull():
|
||||
icon_width = 0
|
||||
else:
|
||||
icon_width = icon.actualSize(QSize(extent, extent)).width()
|
||||
return self._minimum_tab_size_hint_helper(self.tabText(index),
|
||||
icon_width,
|
||||
ellipsis)
|
||||
|
||||
@functools.lru_cache(maxsize=2**9)
|
||||
def _minimum_tab_size_hint_helper(self, tab_text: str,
|
||||
icon_width: int,
|
||||
ellipsis: bool) -> QSize:
|
||||
"""Helper function to cache tab results.
|
||||
|
||||
Config values accessed in here should be added to _on_config_changed to
|
||||
ensure cache is flushed when needed.
|
||||
"""
|
||||
text = '\u2026' if ellipsis else tab_text
|
||||
# Don't ever shorten if text is shorter than the ellipsis
|
||||
text_width = min(self.fontMetrics().width(text),
|
||||
self.fontMetrics().width(self.tabText(index)))
|
||||
icon = self.tabIcon(index)
|
||||
self.fontMetrics().width(tab_text))
|
||||
padding = config.val.tabs.padding
|
||||
indicator_padding = config.val.tabs.indicator_padding
|
||||
padding_h = padding.left + padding.right
|
||||
padding_h += indicator_padding.left + indicator_padding.right
|
||||
padding_v = padding.top + padding.bottom
|
||||
if icon.isNull():
|
||||
icon_size = QSize(0, 0)
|
||||
else:
|
||||
extent = self.style().pixelMetric(QStyle.PM_TabBarIconSize, None,
|
||||
self)
|
||||
icon_size = icon.actualSize(QSize(extent, extent))
|
||||
height = self.fontMetrics().height() + padding_v
|
||||
width = (text_width + icon_size.width() +
|
||||
width = (text_width + icon_width +
|
||||
padding_h + config.val.tabs.width.indicator)
|
||||
return QSize(width, height)
|
||||
|
||||
def _tab_total_width_pinned(self):
|
||||
"""Get the current total width of pinned tabs.
|
||||
|
||||
This width is calculated assuming no shortening due to ellipsis."""
|
||||
return sum(self.minimumTabSizeHint(idx, ellipsis=False).width()
|
||||
for idx in range(self.count())
|
||||
if self._tab_pinned(idx))
|
||||
|
||||
def _pinnedCount(self) -> int:
|
||||
"""Get the number of pinned tabs."""
|
||||
return sum(self._tab_pinned(idx) for idx in range(self.count()))
|
||||
def _pinned_statistics(self) -> (int, int):
|
||||
"""Get the number of pinned tabs and the total width of pinned tabs."""
|
||||
pinned_list = [idx for idx in range(self.count())
|
||||
if self._tab_pinned(idx)]
|
||||
pinned_count = len(pinned_list)
|
||||
pinned_width = sum(self.minimumTabSizeHint(idx, ellipsis=False).width()
|
||||
for idx in pinned_list)
|
||||
return (pinned_count, pinned_width)
|
||||
|
||||
def _tab_pinned(self, index: int) -> bool:
|
||||
"""Return True if tab is pinned."""
|
||||
@ -539,8 +554,8 @@ class TabBar(QTabBar):
|
||||
return QSize()
|
||||
else:
|
||||
pinned = self._tab_pinned(index)
|
||||
no_pinned_count = self.count() - self._pinnedCount()
|
||||
pinned_width = self._tab_total_width_pinned()
|
||||
pinned_count, pinned_width = self._pinned_statistics()
|
||||
no_pinned_count = self.count() - pinned_count
|
||||
no_pinned_width = self.width() - pinned_width
|
||||
|
||||
if pinned:
|
||||
|
@ -182,9 +182,17 @@ def debug_cache_stats():
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window='last-focused')
|
||||
# pylint: disable=protected-access
|
||||
tab_bar = tabbed_browser.tabBar()
|
||||
tabbed_browser_info = tab_bar._minimum_tab_size_hint_helper.cache_info()
|
||||
# pylint: enable=protected-access
|
||||
|
||||
log.misc.debug('is_valid_prefix: {}'.format(prefix_info))
|
||||
log.misc.debug('_render_stylesheet: {}'.format(render_stylesheet_info))
|
||||
log.misc.debug('history: {}'.format(history_info))
|
||||
log.misc.debug('tab width cache: {}'.format(tabbed_browser_info))
|
||||
|
||||
|
||||
@cmdutils.register(debug=True)
|
||||
|
@ -52,3 +52,16 @@ class TestTabWidget:
|
||||
|
||||
with qtbot.waitExposed(widget):
|
||||
widget.show()
|
||||
|
||||
def test_update_tab_titles_benchmark(self, benchmark, widget,
|
||||
qtbot, fake_web_tab):
|
||||
"""Benchmark for update_tab_titles."""
|
||||
widget.addTab(fake_web_tab(), 'foobar')
|
||||
widget.addTab(fake_web_tab(), 'foobar2')
|
||||
widget.addTab(fake_web_tab(), 'foobar3')
|
||||
widget.addTab(fake_web_tab(), 'foobar4')
|
||||
|
||||
with qtbot.waitExposed(widget):
|
||||
widget.show()
|
||||
|
||||
benchmark(widget._update_tab_titles)
|
||||
|
Loading…
Reference in New Issue
Block a user