diff options
Diffstat (limited to 'qutebrowser/mainwindow/tabwidget.py')
-rw-r--r-- | qutebrowser/mainwindow/tabwidget.py | 166 |
1 files changed, 80 insertions, 86 deletions
diff --git a/qutebrowser/mainwindow/tabwidget.py b/qutebrowser/mainwindow/tabwidget.py index 170231f44..b12f40839 100644 --- a/qutebrowser/mainwindow/tabwidget.py +++ b/qutebrowser/mainwindow/tabwidget.py @@ -24,20 +24,14 @@ import contextlib import dataclasses from typing import Optional, Dict, Any -from qutebrowser.qt.core import (pyqtSignal, pyqtSlot, Qt, QSize, QRect, QPoint, - QTimer, QUrl) -from qutebrowser.qt.widgets import (QTabWidget, QTabBar, QSizePolicy, QCommonStyle, - QStyle, QStylePainter, QStyleOptionTab, - QStyleFactory) -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.browser import browsertab +from qutebrowser.qt import widgets, gui, core -class TabWidget(QTabWidget): +class TabWidget(widgets.QTabWidget): """The tab widget used for TabbedBrowser. @@ -48,8 +42,8 @@ class TabWidget(QTabWidget): new_tab_requested: Emitted when a new tab is requested. """ - tab_index_changed = pyqtSignal(int, int) - new_tab_requested = pyqtSignal('QUrl', bool, bool) + tab_index_changed = core.pyqtSignal(int, int) + new_tab_requested = core.pyqtSignal('QUrl', bool, bool) # Strings for controlling the mute/audible text MUTE_STRING = '[M] ' @@ -62,12 +56,12 @@ class TabWidget(QTabWidget): self.setTabBar(bar) bar.tabCloseRequested.connect(self.tabCloseRequested) bar.tabMoved.connect(functools.partial( - QTimer.singleShot, 0, self.update_tab_titles)) + core.QTimer.singleShot, 0, self.update_tab_titles)) bar.currentChanged.connect(self._on_current_changed) bar.new_tab_requested.connect(self._on_new_tab_requested) - self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + self.setSizePolicy(widgets.QSizePolicy.Policy.Expanding, widgets.QSizePolicy.Policy.Fixed) self.setDocumentMode(True) - self.setElideMode(Qt.TextElideMode.ElideRight) + self.setElideMode(core.Qt.TextElideMode.ElideRight) self.setUsesScrollButtons(True) bar.setDrawBase(False) self._init_config() @@ -83,7 +77,7 @@ class TabWidget(QTabWidget): self.setTabPosition(position) tabbar = self.tab_bar() tabbar.vertical = position in [ - QTabWidget.TabPosition.West, QTabWidget.TabPosition.East] + widgets.QTabWidget.TabPosition.West, widgets.QTabWidget.TabPosition.East] tabbar.setSelectionBehaviorOnRemove(selection_behavior) tabbar.refresh() @@ -324,14 +318,14 @@ class TabWidget(QTabWidget): self.set_page_title(new_idx, text) return new_idx - @pyqtSlot(int) + @core.pyqtSlot(int) def _on_current_changed(self, index): """Emit the tab_index_changed signal if the current tab changed.""" self.tab_bar().on_current_changed() self.update_tab_titles() self.tab_index_changed.emit(index, self.count()) - @pyqtSlot() + @core.pyqtSlot() def _on_new_tab_requested(self): """Open a new tab.""" self.new_tab_requested.emit(config.val.url.default_page, False, False) @@ -343,7 +337,7 @@ class TabWidget(QTabWidget): The tab URL as QUrl. """ tab = self._tab_by_idx(idx) - url = QUrl() if tab is None else tab.url() + url = core.QUrl() if tab is None else tab.url() # It's possible for url to be invalid, but the caller will handle that. qtutils.ensure_valid(url) return url @@ -352,13 +346,13 @@ class TabWidget(QTabWidget): """Update favicon of the given tab.""" idx = self.indexOf(tab) - icon = tab.icon() if tab.data.should_show_icon() else QIcon() + icon = tab.icon() if tab.data.should_show_icon() else gui.QIcon() self.setTabIcon(idx, icon) if config.val.tabs.tabs_are_windows: self.window().setWindowIcon(tab.icon()) - def setTabIcon(self, idx: int, icon: QIcon) -> None: + def setTabIcon(self, idx: int, icon: gui.QIcon) -> None: """Always show tab icons for pinned tabs in some circumstances.""" tab = self._tab_by_idx(idx) if (icon.isNull() and @@ -366,11 +360,11 @@ class TabWidget(QTabWidget): config.cache['tabs.pinned.shrink'] and not self.tab_bar().vertical and tab is not None and tab.data.pinned): - icon = self.style().standardIcon(QStyle.StandardPixmap.SP_FileIcon) + icon = self.style().standardIcon(widgets.QStyle.StandardPixmap.SP_FileIcon) super().setTabIcon(idx, icon) -class TabBar(QTabBar): +class TabBar(widgets.QTabBar): """Custom tab bar with our own style. @@ -399,14 +393,14 @@ class TabBar(QTabBar): } """ - new_tab_requested = pyqtSignal() + new_tab_requested = core.pyqtSignal() def __init__(self, win_id, parent=None): super().__init__(parent) self._win_id = win_id self.setStyle(TabBarStyle()) self.vertical = False - self._auto_hide_timer = QTimer() + self._auto_hide_timer = core.QTimer() self._auto_hide_timer.setSingleShot(True) self._auto_hide_timer.timeout.connect(self.maybe_hide) self._on_show_switching_delay_changed() @@ -419,7 +413,7 @@ class TabBar(QTabBar): self.ensurePolished() config.instance.changed.connect(self._on_config_changed) self._set_icon_size() - QTimer.singleShot(0, self.maybe_hide) + core.QTimer.singleShot(0, self.maybe_hide) self._minimum_tab_size_hint_helper = functools.lru_cache(maxsize=2**9)( self._minimum_tab_size_hint_helper_uncached ) @@ -443,7 +437,7 @@ class TabBar(QTabBar): """Get the current tab object.""" return self._tab_widget().currentWidget() - @pyqtSlot(str) + @core.pyqtSlot(str) def _on_config_changed(self, option: str) -> None: if option.startswith('fonts.tabs.'): self.ensurePolished() @@ -480,7 +474,7 @@ class TabBar(QTabBar): self.show() self._auto_hide_timer.start() - @pyqtSlot() + @core.pyqtSlot() def maybe_hide(self): """Hide the tab bar if needed.""" show = config.val.tabs.show @@ -518,7 +512,7 @@ class TabBar(QTabBar): try: return self.tab_data(idx, 'indicator-color') except KeyError: - return QColor() + return gui.QColor() def page_title(self, idx): """Get the tab title user data. @@ -541,7 +535,7 @@ class TabBar(QTabBar): """Set the tab bar favicon size.""" size = self.fontMetrics().height() - 2 size = int(size * config.val.tabs.favicons.scale) - self.setIconSize(QSize(size, size)) + self.setIconSize(core.QSize(size, size)) def mouseReleaseEvent(self, e): """Override mouseReleaseEvent to know when drags stop.""" @@ -554,8 +548,8 @@ class TabBar(QTabBar): Also keep track of if we are currently in a drag.""" self.drag_in_progress = True button = config.val.tabs.close_mouse_button - if (e.button() == Qt.MouseButton.RightButton and button == 'right' or - e.button() == Qt.MouseButton.MiddleButton and button == 'middle'): + if (e.button() == core.Qt.MouseButton.RightButton and button == 'right' or + e.button() == core.Qt.MouseButton.MiddleButton and button == 'middle'): e.accept() idx = self.tabAt(e.pos()) if idx == -1: @@ -573,7 +567,7 @@ class TabBar(QTabBar): return super().mousePressEvent(e) - def minimumTabSizeHint(self, index: int, ellipsis: bool = True) -> QSize: + def minimumTabSizeHint(self, index: int, ellipsis: bool = True) -> core.QSize: """Set the minimum tab size to indicator/icon/... text. Args: @@ -602,7 +596,7 @@ class TabBar(QTabBar): def _minimum_tab_size_hint_helper_uncached(self, tab_text: str, icon_width: int, - ellipsis: bool, pinned: bool) -> QSize: + ellipsis: bool, pinned: bool) -> core.QSize: """Helper function to cache tab results. Config values accessed in here should be added to _on_config_changed to @@ -613,7 +607,7 @@ class TabBar(QTabBar): def _text_to_width(text): # Calculate text width taking into account qt mnemonics - return self.fontMetrics().size(Qt.TextFlag.TextShowMnemonic, text).width() + return self.fontMetrics().size(core.Qt.TextFlag.TextShowMnemonic, text).width() text_width = min(_text_to_width(text), _text_to_width(tab_text)) padding = config.cache['tabs.padding'] @@ -631,7 +625,7 @@ class TabBar(QTabBar): if (not self.vertical and min_width > 0 and not pinned or not config.cache['tabs.pinned.shrink']): width = max(min_width, width) - return QSize(width, height) + return core.QSize(width, height) def _minimum_tab_height_uncached(self): padding = config.cache['tabs.padding'] @@ -650,7 +644,7 @@ class TabBar(QTabBar): return False return widget.data.pinned - def tabSizeHint(self, index: int) -> QSize: + def tabSizeHint(self, index: int) -> core.QSize: """Override tabSizeHint to customize qb's tab size. https://wiki.python.org/moin/PyQt/Customising%20tab%20bars @@ -665,7 +659,7 @@ class TabBar(QTabBar): # This happens on startup on macOS. # We return it directly rather than setting `size' because we don't # want to ensure it's valid in this special case. - return QSize() + return core.QSize() height = self._minimum_tab_height() if self.vertical: @@ -677,7 +671,7 @@ class TabBar(QTabBar): width = main_window.width() * perc // 100 else: width = int(confwidth) - size = QSize(width, height) + size = core.QSize(width, height) else: if config.cache['tabs.pinned.shrink'] and self._tab_pinned(index): # Give pinned tabs the minimum size they need to display their @@ -691,20 +685,20 @@ class TabBar(QTabBar): max_width = config.cache['tabs.max_width'] if max_width > 0: width = min(max_width, width) - size = QSize(width, height) + size = core.QSize(width, height) qtutils.ensure_valid(size) return size def paintEvent(self, event): """Override paintEvent to draw the tabs like we want to.""" - p = QStylePainter(self) + p = widgets.QStylePainter(self) selected = self.currentIndex() for idx in range(self.count()): if not event.region().intersects(self.tabRect(idx)): # Don't repaint if we are outside the requested region continue - tab = QStyleOptionTab() + tab = widgets.QStyleOptionTab() self.initStyleOption(tab, idx) setting = 'colors.tabs' @@ -714,14 +708,14 @@ class TabBar(QTabBar): setting += '.selected' setting += '.odd' if (idx + 1) % 2 else '.even' - tab.palette.setColor(QPalette.ColorRole.Window, + tab.palette.setColor(gui.QPalette.ColorRole.Window, config.cache[setting + '.bg']) - tab.palette.setColor(QPalette.ColorRole.WindowText, + tab.palette.setColor(gui.QPalette.ColorRole.WindowText, config.cache[setting + '.fg']) indicator_color = self.tab_indicator_color(idx) - tab.palette.setColor(QPalette.ColorRole.Base, indicator_color) - p.drawControl(QStyle.ControlElement.CE_TabBarTab, tab) + tab.palette.setColor(gui.QPalette.ColorRole.Base, indicator_color) + p.drawControl(widgets.QStyle.ControlElement.CE_TabBarTab, tab) def tabInserted(self, idx): """Update visibility when a tab was inserted.""" @@ -769,12 +763,12 @@ class Layouts: Used by TabBarStyle._tab_layout(). """ - text: QRect - icon: QRect - indicator: QRect + text: core.QRect + icon: core.QRect + indicator: core.QRect -class TabBarStyle(QCommonStyle): +class TabBarStyle(widgets.QCommonStyle): """Qt style used by TabBar to fix some issues with the default one. @@ -799,7 +793,7 @@ class TabBarStyle(QCommonStyle): This simply calls the corresponding function in self._style. """ - self._style = QStyleFactory.create('Fusion') + self._style = widgets.QStyleFactory.create('Fusion') for method in ['drawComplexControl', 'drawItemPixmap', 'generatedIconPixmap', 'hitTestComplexControl', 'itemPixmapRect', 'itemTextRect', 'polish', 'styleHint', @@ -831,12 +825,12 @@ class TabBarStyle(QCommonStyle): p: QPainter """ qtutils.ensure_valid(layouts.icon) - icon_mode = (QIcon.Mode.Normal if opt.state & QStyle.StateFlag.State_Enabled - else QIcon.Mode.Disabled) - icon_state = (QIcon.State.On if opt.state & QStyle.StateFlag.State_Selected - else QIcon.State.Off) + icon_mode = (gui.QIcon.Mode.Normal if opt.state & widgets.QStyle.StateFlag.State_Enabled + else gui.QIcon.Mode.Disabled) + icon_state = (gui.QIcon.State.On if opt.state & widgets.QStyle.StateFlag.State_Selected + else gui.QIcon.State.Off) icon = opt.icon.pixmap(opt.iconSize, icon_mode, icon_state) - self._style.drawItemPixmap(p, layouts.icon, Qt.AlignmentFlag.AlignCenter, icon) + self._style.drawItemPixmap(p, layouts.icon, core.Qt.AlignmentFlag.AlignCenter, icon) def drawControl(self, element, opt, p, widget=None): """Override drawControl to draw odd tabs in a different color. @@ -850,8 +844,8 @@ class TabBarStyle(QCommonStyle): p: QPainter widget: QWidget """ - if element not in [QStyle.ControlElement.CE_TabBarTab, QStyle.ControlElement.CE_TabBarTabShape, - QStyle.ControlElement.CE_TabBarTabLabel]: + if element not in [widgets.QStyle.ControlElement.CE_TabBarTab, widgets.QStyle.ControlElement.CE_TabBarTabShape, + widgets.QStyle.ControlElement.CE_TabBarTabLabel]: # Let the real style draw it. self._style.drawControl(element, opt, p, widget) return @@ -861,28 +855,28 @@ class TabBarStyle(QCommonStyle): log.misc.warning("Could not get layouts for tab!") return - if element == QStyle.ControlElement.CE_TabBarTab: + if element == widgets.QStyle.ControlElement.CE_TabBarTab: # We override this so we can control TabBarTabShape/TabBarTabLabel. - self.drawControl(QStyle.ControlElement.CE_TabBarTabShape, opt, p, widget) - self.drawControl(QStyle.ControlElement.CE_TabBarTabLabel, opt, p, widget) - elif element == QStyle.ControlElement.CE_TabBarTabShape: + self.drawControl(widgets.QStyle.ControlElement.CE_TabBarTabShape, opt, p, widget) + self.drawControl(widgets.QStyle.ControlElement.CE_TabBarTabLabel, opt, p, widget) + elif element == widgets.QStyle.ControlElement.CE_TabBarTabShape: p.fillRect(opt.rect, opt.palette.window()) self._draw_indicator(layouts, opt, p) # We use super() rather than self._style here because we don't want # any sophisticated drawing. - super().drawControl(QStyle.ControlElement.CE_TabBarTabShape, opt, p, widget) - elif element == QStyle.ControlElement.CE_TabBarTabLabel: + super().drawControl(widgets.QStyle.ControlElement.CE_TabBarTabShape, opt, p, widget) + elif element == widgets.QStyle.ControlElement.CE_TabBarTabLabel: if not opt.icon.isNull() and layouts.icon.isValid(): self._draw_icon(layouts, opt, p) alignment = (config.cache['tabs.title.alignment'] | - Qt.AlignmentFlag.AlignVCenter | Qt.TextFlag.TextHideMnemonic) + core.Qt.AlignmentFlag.AlignVCenter | core.Qt.TextFlag.TextHideMnemonic) self._style.drawItemText(p, layouts.text, int(alignment), opt.palette, - bool(opt.state & QStyle.StateFlag.State_Enabled), + bool(opt.state & widgets.QStyle.StateFlag.State_Enabled), opt.text, - QPalette.ColorRole.WindowText) + gui.QPalette.ColorRole.WindowText) else: raise ValueError("Invalid element {!r}".format(element)) @@ -897,11 +891,11 @@ class TabBarStyle(QCommonStyle): Return: An int. """ - if metric in [QStyle.PixelMetric.PM_TabBarTabShiftHorizontal, - QStyle.PixelMetric.PM_TabBarTabShiftVertical, - QStyle.PixelMetric.PM_TabBarTabHSpace, - QStyle.PixelMetric.PM_TabBarTabVSpace, - QStyle.PixelMetric.PM_TabBarScrollButtonWidth]: + if metric in [widgets.QStyle.PixelMetric.PM_TabBarTabShiftHorizontal, + widgets.QStyle.PixelMetric.PM_TabBarTabShiftVertical, + widgets.QStyle.PixelMetric.PM_TabBarTabHSpace, + widgets.QStyle.PixelMetric.PM_TabBarTabVSpace, + widgets.QStyle.PixelMetric.PM_TabBarScrollButtonWidth]: return 0 else: return self._style.pixelMetric(metric, option, widget) @@ -917,14 +911,14 @@ class TabBarStyle(QCommonStyle): Return: A QRect. """ - if sr == QStyle.SubElement.SE_TabBarTabText: + if sr == widgets.QStyle.SubElement.SE_TabBarTabText: layouts = self._tab_layout(opt) if layouts is None: log.misc.warning("Could not get layouts for tab!") - return QRect() + return core.QRect() return layouts.text - elif sr in [QStyle.SubElement.SE_TabWidgetTabBar, - QStyle.SubElement.SE_TabBarScrollLeftButton]: + elif sr in [widgets.QStyle.SubElement.SE_TabWidgetTabBar, + widgets.QStyle.SubElement.SE_TabBarScrollLeftButton]: # Handling SE_TabBarScrollLeftButton so the left scroll button is # aligned properly. Otherwise, empty space will be shown after the # last tab even though the button width is set to 0 @@ -952,7 +946,7 @@ class TabBarStyle(QCommonStyle): padding = config.cache['tabs.padding'] indicator_padding = config.cache['tabs.indicator.padding'] - text_rect = QRect(opt.rect) + text_rect = core.QRect(opt.rect) if not text_rect.isValid(): # This happens sometimes according to crash reports, but no idea # why... @@ -963,9 +957,9 @@ class TabBarStyle(QCommonStyle): indicator_width = config.cache['tabs.indicator.width'] if indicator_width == 0: - indicator_rect = QRect() + indicator_rect = core.QRect() else: - indicator_rect = QRect(opt.rect) + indicator_rect = core.QRect(opt.rect) qtutils.ensure_valid(indicator_rect) indicator_rect.adjust(padding.left + indicator_padding.left, padding.top + indicator_padding.top, @@ -997,24 +991,24 @@ class TabBarStyle(QCommonStyle): """ icon_size = opt.iconSize if not icon_size.isValid(): - icon_extent = self.pixelMetric(QStyle.PixelMetric.PM_SmallIconSize) - icon_size = QSize(icon_extent, icon_extent) - icon_mode = (QIcon.Mode.Normal if opt.state & QStyle.StateFlag.State_Enabled - else QIcon.Mode.Disabled) - icon_state = (QIcon.State.On if opt.state & QStyle.StateFlag.State_Selected - else QIcon.State.Off) + icon_extent = self.pixelMetric(widgets.QStyle.PixelMetric.PM_SmallIconSize) + icon_size = core.QSize(icon_extent, icon_extent) + icon_mode = (gui.QIcon.Mode.Normal if opt.state & widgets.QStyle.StateFlag.State_Enabled + else gui.QIcon.Mode.Disabled) + icon_state = (gui.QIcon.State.On if opt.state & widgets.QStyle.StateFlag.State_Selected + else gui.QIcon.State.Off) # reserve space for favicon when tab bar is vertical (issue #1968) position = config.cache['tabs.position'] - if (position in [QTabWidget.TabPosition.East, QTabWidget.TabPosition.West] and + if (position in [widgets.QTabWidget.TabPosition.East, widgets.QTabWidget.TabPosition.West] and config.cache['tabs.favicons.show'] != 'never'): tab_icon_size = icon_size else: actual_size = opt.icon.actualSize(icon_size, icon_mode, icon_state) - tab_icon_size = QSize( + tab_icon_size = core.QSize( min(actual_size.width(), icon_size.width()), min(actual_size.height(), icon_size.height())) icon_top = text_rect.center().y() + 1 - tab_icon_size.height() // 2 - icon_rect = QRect(QPoint(text_rect.left(), icon_top), tab_icon_size) + icon_rect = core.QRect(core.QPoint(text_rect.left(), icon_top), tab_icon_size) icon_rect = self._style.visualRect(opt.direction, opt.rect, icon_rect) return icon_rect |