1
0

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
This commit is contained in:
SomberNight
2022-07-29 19:12:48 +02:00
parent ad9030bd15
commit 7dcd8d8dc8
2 changed files with 66 additions and 44 deletions

View File

@@ -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

View File

@@ -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)