Scroll tab bar so current tab isn't at an edge

It is unfortunate that everything we could override to fix the "gravity"
of the visible portion of the tab bar is in QTabBarPrivate. Also that it
has no public API for scrolling ... except for the buttons.

Gets the QToolButtons that are children of the QTabWidget (actually of
the QTabBarPrivate) and uses them to scroll the tab bar. Only works
because they aren't hidden, they are just of zero size.

Gets the tab indices at the edges of the tab bar and compares them to
the current tab and if there is less than 5 tabs differnce it scrolls
across to make up the difference. I didn't bother making the padding
count configurable because I doubt this'll get merged.

The throttle is mostly for resizing and shutting down (not sure why that
is not a decorator).
This commit is contained in:
Jimmy 2019-12-07 18:04:43 +13:00 committed by toofar
parent 7750a2f7a2
commit 5b3597613a
1 changed files with 53 additions and 2 deletions

View File

@ -13,13 +13,14 @@ from qutebrowser.qt.core import (pyqtSignal, pyqtSlot, Qt, QSize, QRect, QPoint,
QTimer, QUrl)
from qutebrowser.qt.widgets import (QTabWidget, QTabBar, QSizePolicy, QProxyStyle,
QStyle, QStylePainter, QStyleOptionTab,
QCommonStyle)
QCommonStyle, QToolButton)
from qutebrowser.qt.gui import QIcon, QPalette, QColor
from qutebrowser.utils import qtutils, objreg, utils, usertypes, log
from qutebrowser.config import config, stylesheet
from qutebrowser.misc import objects, debugcachestats
from qutebrowser.misc import objects, debugcachestats, throttle
from qutebrowser.browser import browsertab
from qutebrowser.qt import sip
class TabWidget(QTabWidget):
@ -42,6 +43,7 @@ class TabWidget(QTabWidget):
def __init__(self, win_id, parent=None):
super().__init__(parent)
self.scroll_tab_bar = throttle.Throttle(self._scroll_tab_bar, 100)
bar = TabBar(win_id, self)
self.setStyle(TabBarStyle())
self.setTabBar(bar)
@ -56,6 +58,7 @@ class TabWidget(QTabWidget):
bar.setDrawBase(False)
self._init_config()
config.instance.changed.connect(self._init_config)
self._scroll_left, self._scroll_right = self.findChildren(QToolButton)
@config.change_filter('tabs')
def _init_config(self):
@ -316,6 +319,49 @@ class TabWidget(QTabWidget):
self.tab_bar().on_current_changed()
self.update_tab_titles()
self.tab_index_changed.emit(index, self.count())
QTimer.singleShot(0, self.scroll_tab_bar)
def _scroll_tab_bar(self):
"""Scroll tab bar so that the current tab is not at an edge."""
if sip.isdeleted(self):
# probably called async while shutting down
return
num_tabs = 5 # padding required
idx = self.currentIndex()
if idx < 0:
return
position = config.cache['tabs.position']
if position == QTabWidget.TabPosition.North:
start = self.rect().topLeft()
end = self.rect().topRight()
elif position == QTabWidget.TabPosition.South:
start = self.rect().bottomLeft()
end = self.rect().bottomRight()
elif position == QTabWidget.TabPosition.West:
start = self.rect().topLeft()
end = self.rect().bottomLeft()
elif position == QTabWidget.TabPosition.East:
start = self.rect().topRight()
end = self.rect().bottomRight()
start_idx = self.tabBar().tabAt(start)
end_idx = self.tabBar().tabAt(end)
if start_idx < 0 or end_idx < 0:
log.misc.warning("Could not get tabs at edges of tab bar.")
return
count = num_tabs - (end_idx - idx)
if count > 0:
for _ in range(count):
self._scroll_right.click()
return
count = idx - start_idx
if count < num_tabs:
for _ in range(num_tabs - count):
self._scroll_left.click()
return
@pyqtSlot()
def _on_new_tab_requested(self):
@ -775,6 +821,11 @@ class TabBar(QTabBar):
window=self._win_id)
tabbed_browser.wheelEvent(e)
@pyqtSlot()
def tabLayoutChange(self):
if self.currentIndex() > -1:
QTimer.singleShot(0, self.parent().scroll_tab_bar)
@dataclasses.dataclass
class Layouts: