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