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