diff --git a/electrum/gui/qt/receive_tab.py b/electrum/gui/qt/receive_tab.py index 42a701f49..38fc63bb2 100644 --- a/electrum/gui/qt/receive_tab.py +++ b/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')) @@ -395,7 +395,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 diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py index 313a74235..021a8eb42 100644 --- a/electrum/gui/qt/util.py +++ b/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)