qutebrowser/qutebrowser/widgets/tabwidget.py

166 lines
5.4 KiB
Python
Raw Normal View History

2014-06-19 09:04:37 +02:00
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
2014-02-06 14:01:23 +01:00
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
2014-02-17 12:23:52 +01:00
"""The tab widget used for TabbedBrowser from browser.py."""
2014-07-11 07:01:08 +02:00
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QSize
2014-05-26 12:17:43 +02:00
from PyQt5.QtWidgets import QTabWidget, QTabBar, QSizePolicy
2014-05-12 21:23:16 +02:00
from PyQt5.QtGui import QIcon, QPixmap
2013-12-15 20:29:39 +01:00
2014-02-23 18:07:17 +01:00
import qutebrowser.config.config as config
from qutebrowser.config.style import set_register_stylesheet
from qutebrowser.utils.style import Style
2014-06-23 07:45:04 +02:00
from qutebrowser.utils.qt import qt_ensure_valid
2014-01-28 12:21:00 +01:00
2014-01-28 23:04:02 +01:00
2014-05-12 21:23:16 +02:00
class EmptyTabIcon(QIcon):
"""An empty icon for a tab.
Qt somehow cuts text off when padding is used for the tabbar, see
https://bugreports.qt-project.org/browse/QTBUG-15203
Until we find a better solution we use this hack of using a simple
transparent icon to get some padding, because when a real favicon is set,
the padding seems to be fine...
"""
def __init__(self):
pix = QPixmap(2, 16)
pix.fill(Qt.transparent)
super().__init__(pix)
2013-12-15 20:29:39 +01:00
class TabWidget(QTabWidget):
2014-02-07 20:21:50 +01:00
2014-02-18 16:38:13 +01:00
"""The tabwidget used for TabbedBrowser.
2014-04-17 17:44:27 +02:00
Class attributes:
STYLESHEET: The stylesheet template to be used.
2014-02-18 16:38:13 +01:00
"""
2013-12-15 20:29:39 +01:00
STYLESHEET = """
2014-01-28 12:21:00 +01:00
QTabWidget::pane {{
position: absolute;
top: 0px;
2014-01-28 12:21:00 +01:00
}}
2014-01-28 12:21:00 +01:00
QTabBar {{
2014-02-10 07:03:51 +01:00
{font[tabbar]}
2014-04-22 20:49:16 +02:00
{color[tab.bg.bar]}
2014-01-28 12:21:00 +01:00
}}
2013-12-15 20:29:39 +01:00
2014-01-28 12:21:00 +01:00
QTabBar::tab {{
{color[tab.bg]}
{color[tab.fg]}
2014-05-01 21:30:29 +02:00
border-right: 2px solid {color[tab.seperator]};
2014-05-12 16:04:43 +02:00
min-width: {config[tabbar][min-tab-width]}px;
max-width: {config[tabbar][max-tab-width]}px;
2014-06-24 11:03:44 +02:00
margin: 0px;
2014-01-28 12:21:00 +01:00
}}
2014-01-27 23:12:43 +01:00
2014-01-28 12:21:00 +01:00
QTabBar::tab:selected {{
{color[tab.bg.selected]}
}}
"""
def __init__(self, parent):
super().__init__(parent)
2014-05-23 04:12:18 +02:00
self.setTabBar(TabBar())
2014-01-30 22:29:01 +01:00
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
self.setStyle(Style(self.style()))
set_register_stylesheet(self)
2013-12-15 20:29:39 +01:00
self.setDocumentMode(True)
2014-01-19 16:56:33 +01:00
self.setElideMode(Qt.ElideRight)
2014-04-22 20:49:16 +02:00
self.tabBar().setDrawBase(False)
2014-02-13 08:56:01 +01:00
self._init_config()
def _init_config(self):
"""Initialize attributes based on the config."""
position_conv = {
'north': QTabWidget.North,
'south': QTabWidget.South,
'west': QTabWidget.West,
'east': QTabWidget.East,
}
select_conv = {
'left': QTabBar.SelectLeftTab,
'right': QTabBar.SelectRightTab,
'previous': QTabBar.SelectPreviousTab,
}
self.setMovable(config.get('tabbar', 'movable'))
2014-04-27 21:21:14 +02:00
self.setTabsClosable(config.get('tabbar', 'close-buttons'))
self.setUsesScrollButtons(config.get('tabbar', 'scroll-buttons'))
posstr = config.get('tabbar', 'position')
2014-04-27 21:21:14 +02:00
selstr = config.get('tabbar', 'select-on-remove')
2014-06-21 22:40:31 +02:00
self.setTabPosition(position_conv[posstr])
self.tabBar().setSelectionBehaviorOnRemove(select_conv[selstr])
@pyqtSlot(str, str)
2014-04-22 17:53:27 +02:00
def on_config_changed(self, section, _option):
"""Update attributes when config changed."""
if section == 'tabbar':
self._init_config()
2014-05-23 04:12:18 +02:00
class TabBar(QTabBar):
2014-07-11 07:01:08 +02:00
"""Custom tabbar to close tabs on right click.
Signals:
tab_rightclicked: Emitted when a tab was right-clicked and should be
closed. We use this rather than tabCloseRequested
because tabCloseRequested is sometimes connected by
Qt to the tabwidget and sometimes not, depending on
if close buttons are enabled.
arg: The tab index to be closed.
"""
tab_rightclicked = pyqtSignal(int)
2014-05-23 04:12:18 +02:00
def __repr__(self):
return '<{} with {} tabs>'.format(self.__class__.__name__,
self.count())
2014-05-23 04:12:18 +02:00
def mousePressEvent(self, e):
"""Override mousePressEvent to emit tabCloseRequested on rightclick."""
2014-07-11 07:01:08 +02:00
if e.button() != Qt.RightButton:
2014-06-22 23:37:16 +02:00
super().mousePressEvent(e)
return
2014-05-23 04:12:18 +02:00
idx = self.tabAt(e.pos())
if idx == -1:
2014-06-22 23:37:16 +02:00
super().mousePressEvent(e)
return
2014-06-23 18:21:12 +02:00
e.accept()
2014-07-11 07:01:08 +02:00
if config.get('tabbar', 'close-on-right-click'):
self.tab_rightclicked.emit(idx)
2014-06-10 14:30:31 +02:00
def tabSizeHint(self, index):
"""Override tabSizeHint so all tabs are the same size.
https://wiki.python.org/moin/PyQt/Customising%20tab%20bars
"""
if config.get('tabbar', 'expand'):
height = super().tabSizeHint(index).height()
2014-06-22 23:32:49 +02:00
size = QSize(self.width() / self.count(), height)
2014-06-10 14:30:31 +02:00
else:
2014-06-22 23:32:49 +02:00
size = super().tabSizeHint(index)
qt_ensure_valid(size)
return size