Browse Source

Qt receive_tab: fix receive_tabs widget on macOS

QTabWidget with "West" tab pos and horizontal text looks completely broken on macOS
(despite looking good on e.g. Ubuntu GNOME and Windows).

The alternative here looks ok on all three OSes.

fixes https://github.com/spesmilo/electrum/issues/7908
patch-4
SomberNight 3 years ago
parent
commit
7dcd8d8dc8
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 4
      electrum/gui/qt/receive_tab.py
  2. 106
      electrum/gui/qt/util.py

4
electrum/gui/qt/receive_tab.py

@ -155,7 +155,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
from .util import VTabWidget
self.receive_tabs = VTabWidget()
self.receive_tabs.setMinimumHeight(ReceiveTabWidget.min_size.height() + 4) # for margins
#self.receive_tabs.setMinimumHeight(ReceiveTabWidget.min_size.height() + 4) # for margins
self.receive_tabs.addTab(self.receive_URI_widget, read_QIcon("link.png"), _('URI'))
self.receive_tabs.addTab(self.receive_address_widget, read_QIcon("bitcoin.png"), _('Address'))
self.receive_tabs.addTab(self.receive_lightning_widget, read_QIcon("lightning.png"), _('Lightning'))
@ -392,7 +392,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
class ReceiveTabWidget(QWidget):
min_size = QSize(200, 200)
def __init__(self, receive_tab: 'ReceiveTab', textedit, qr, help_widget):
def __init__(self, receive_tab: 'ReceiveTab', textedit: QWidget, qr: QWidget, help_widget: QWidget):
self.textedit = textedit
self.qr = qr
self.help_widget = help_widget

106
electrum/gui/qt/util.py

@ -12,6 +12,7 @@ from functools import partial, lru_cache, wraps
from typing import (NamedTuple, Callable, Optional, TYPE_CHECKING, Union, List, Dict, Any,
Sequence, Iterable, Tuple)
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtGui import (QFont, QColor, QCursor, QPixmap, QStandardItem, QImage,
QPalette, QIcon, QFontMetrics, QShowEvent, QPainter, QHelpEvent)
from PyQt5.QtCore import (Qt, QPersistentModelIndex, QModelIndex, pyqtSignal,
@ -24,7 +25,7 @@ from PyQt5.QtWidgets import (QPushButton, QLabel, QMessageBox, QHBoxLayout,
QFileDialog, QWidget, QToolButton, QTreeView, QPlainTextEdit,
QHeaderView, QApplication, QToolTip, QTreeWidget, QStyledItemDelegate,
QMenu, QStyleOptionViewItem, QLayout, QLayoutItem, QAbstractButton,
QGraphicsEffect, QGraphicsScene, QGraphicsPixmapItem)
QGraphicsEffect, QGraphicsScene, QGraphicsPixmapItem, QSizePolicy)
from electrum.i18n import _, languages
from electrum.util import FileImportFailed, FileExportFailed, make_aiohttp_session, resource_path
@ -1570,54 +1571,75 @@ class ImageGraphicsEffect(QObject):
return result
# vertical tabs
# from https://stackoverflow.com/questions/51230544/pyqt5-how-to-set-tabwidget-west-but-keep-the-text-horizontal
from PyQt5 import QtWidgets, QtCore
class VTabBar(QtWidgets.QTabBar):
def tabSizeHint(self, index):
s = QtWidgets.QTabBar.tabSizeHint(self, index)
s.transpose()
return s
def paintEvent(self, event):
painter = QtWidgets.QStylePainter(self)
opt = QtWidgets.QStyleOptionTab()
for i in range(self.count()):
self.initStyleOption(opt, i)
painter.drawControl(QtWidgets.QStyle.CE_TabBarTabShape, opt)
painter.save()
s = opt.rect.size()
s.transpose()
r = QtCore.QRect(QtCore.QPoint(), s)
r.moveCenter(opt.rect.center())
opt.rect = r
c = self.tabRect(i).center()
painter.translate(c)
painter.rotate(90)
painter.translate(-c)
painter.drawControl(QtWidgets.QStyle.CE_TabBarTabLabel, opt);
painter.restore()
class VTabWidget(QtWidgets.QTabWidget):
def __init__(self, *args, **kwargs):
QtWidgets.QTabWidget.__init__(self, *args, **kwargs)
self.setTabBar(VTabBar(self))
self.setTabPosition(QtWidgets.QTabWidget.West)
class SquareTabWidget(QtWidgets.QTabWidget):
def resizeEvent(self, e):
# keep square aspect ratio when resized
size = e.size()
w = self.tabBar().width() + size.height()
w = size.height()
w += self.tabBar().width() if self.tabBar().isVisible() else 0
self.setFixedWidth(w)
return super().resizeEvent(e)
class VTabWidget(QWidget):
"""QtWidgets.QTabWidget alternative with "West" tab positions and horizontal tab-text."""
def __init__(self):
QWidget.__init__(self)
hbox = QHBoxLayout()
self.setLayout(hbox)
hbox.setContentsMargins(0, 0, 0, 0)
hbox.setSpacing(0)
self._tabs_vbox = tabs_vbox = QVBoxLayout()
self._tab_btns = [] # type: List[QPushButton]
tabs_vbox.setContentsMargins(0, 0, 0, 0)
tabs_vbox.setSpacing(0)
_tabs_vbox_outer_w = QWidget()
_tabs_vbox_outer = QVBoxLayout()
_tabs_vbox_outer_w.setLayout(_tabs_vbox_outer)
_tabs_vbox_outer_w.setSizePolicy(QSizePolicy(QSizePolicy.Maximum, _tabs_vbox_outer_w.sizePolicy().verticalPolicy()))
_tabs_vbox_outer.setContentsMargins(0, 0, 0, 0)
_tabs_vbox_outer.setSpacing(0)
_tabs_vbox_outer.addLayout(tabs_vbox)
_tabs_vbox_outer.addStretch(1)
self.content_w = content_w = SquareTabWidget()
content_w.setStyleSheet("QTabBar::tab {height: 0px;}") # TODO Linux/mac: still insufficient to rm top padding...
content_w.tabBar().hide()
hbox.addStretch(1)
hbox.addWidget(_tabs_vbox_outer_w)
hbox.addWidget(content_w)
self.currentChanged = content_w.currentChanged
self.currentIndex = content_w.currentIndex
def addTab(self, widget: QWidget, icon: QIcon, text: str):
btn = QPushButton(icon, text)
btn.setCheckable(True)
btn.setSizePolicy(QSizePolicy.Preferred, btn.sizePolicy().verticalPolicy())
def on_btn_click():
self.content_w.setCurrentIndex(idx)
for btn2 in self._tab_btns:
if btn2 != btn:
btn2.setChecked(False)
btn.clicked.connect(on_btn_click)
idx = len(self._tab_btns)
self._tab_btns.append(btn)
self._tabs_vbox.addWidget(btn)
self.content_w.addTab(widget, "")
def setTabIcon(self, idx: int, icon: QIcon):
self._tab_btns[idx].setIcon(icon)
def setCurrentIndex(self, idx: int):
self._tab_btns[idx].click()
class QtEventListener(EventListener):
qt_callback_signal = QtCore.pyqtSignal(tuple)

Loading…
Cancel
Save