From db37938963c1b6a430e9c88d1a189f26a53e9fab Mon Sep 17 00:00:00 2001 From: SomberNight Date: Tue, 23 Mar 2021 21:34:04 +0100 Subject: [PATCH] qt channels list: add "features" column with icons (e.g. trampoline) --- electrum/gui/icons/kangaroo.png | Bin 0 -> 15433 bytes electrum/gui/icons/nocloud.png | Bin 0 -> 14573 bytes electrum/gui/qt/channels_list.py | 93 ++++++++++++++++++++++++++++--- electrum/gui/qt/util.py | 36 +++++++++++- 4 files changed, 119 insertions(+), 10 deletions(-) create mode 100644 electrum/gui/icons/kangaroo.png create mode 100644 electrum/gui/icons/nocloud.png diff --git a/electrum/gui/icons/kangaroo.png b/electrum/gui/icons/kangaroo.png new file mode 100644 index 0000000000000000000000000000000000000000..e27d4f81b72418ad03663809240bd27320c3595b GIT binary patch literal 15433 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 str: + pass + + @abstractmethod + def icon(self) -> QIcon: + pass + + +class ChanFeatTrampoline(ChannelFeature): + def tooltip(self) -> str: + return _("The channel peer can route Trampoline payments.") + def icon(self) -> QIcon: + return read_QIcon("kangaroo") + + +class ChanFeatNoOnchainBackup(ChannelFeature): + def tooltip(self) -> str: + return _("This channel cannot be recovered from your seed. You must back it up manually.") + def icon(self) -> QIcon: + return read_QIcon("nocloud") + + +class ChannelFeatureIcons: + ICON_SIZE = QSize(16, 16) + + def __init__(self, features: Sequence['ChannelFeature']): + self.features = features + + @classmethod + def from_channel(cls, chan: AbstractChannel) -> 'ChannelFeatureIcons': + if not isinstance(chan, Channel): + return ChannelFeatureIcons([]) + feats = [] + if chan.lnworker.is_trampoline_peer(chan.node_id): + feats.append(ChanFeatTrampoline()) + if not chan.lnworker.has_recoverable_channels(): + feats.append(ChanFeatNoOnchainBackup()) + return ChannelFeatureIcons(feats) + + def paint(self, painter: QPainter, rect: QRect) -> None: + painter.save() + cur_x = rect.x() + for feat in self.features: + icon_rect = QRect(cur_x, rect.y(), self.ICON_SIZE.width(), self.ICON_SIZE.height()) + feat.rect = icon_rect + if rect.contains(icon_rect): # stay inside parent + painter.drawPixmap(icon_rect, feat.icon().pixmap(self.ICON_SIZE)) + cur_x += self.ICON_SIZE.width() + 1 + painter.restore() + + def sizeHint(self, default_size: QSize) -> QSize: + if not self.features: + return default_size + width = len(self.features) * (self.ICON_SIZE.width() + 1) + return QSize(width, default_size.height()) + + def show_tooltip(self, evt: QHelpEvent) -> bool: + assert isinstance(evt, QHelpEvent) + for feat in self.features: + if feat.rect.contains(evt.pos()): + QToolTip.showText(evt.globalPos(), feat.tooltip()) + break + else: + QToolTip.hideText() + evt.ignore() + return True diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py index 36ed71617..676e85fc7 100644 --- a/electrum/gui/qt/util.py +++ b/electrum/gui/qt/util.py @@ -13,16 +13,17 @@ from typing import (NamedTuple, Callable, Optional, TYPE_CHECKING, Union, List, Sequence, Iterable) from PyQt5.QtGui import (QFont, QColor, QCursor, QPixmap, QStandardItem, - QPalette, QIcon, QFontMetrics, QShowEvent) + QPalette, QIcon, QFontMetrics, QShowEvent, QPainter, QHelpEvent) from PyQt5.QtCore import (Qt, QPersistentModelIndex, QModelIndex, pyqtSignal, QCoreApplication, QItemSelectionModel, QThread, - QSortFilterProxyModel, QSize, QLocale, QAbstractItemModel) + QSortFilterProxyModel, QSize, QLocale, QAbstractItemModel, + QEvent) from PyQt5.QtWidgets import (QPushButton, QLabel, QMessageBox, QHBoxLayout, QAbstractItemView, QVBoxLayout, QLineEdit, QStyle, QDialog, QGroupBox, QButtonGroup, QRadioButton, QFileDialog, QWidget, QToolButton, QTreeView, QPlainTextEdit, QHeaderView, QApplication, QToolTip, QTreeWidget, QStyledItemDelegate, - QMenu) + QMenu, QStyleOptionViewItem) from electrum.i18n import _, languages from electrum.util import FileImportFailed, FileExportFailed, make_aiohttp_session, resource_path @@ -518,9 +519,38 @@ class ElectrumItemDelegate(QStyledItemDelegate): self.tv.is_editor_open = True return super().createEditor(parent, option, idx) + def paint(self, painter: QPainter, option: QStyleOptionViewItem, idx: QModelIndex) -> None: + custom_data = idx.data(MyTreeView.ROLE_CUSTOM_PAINT) + if custom_data is None: + return super().paint(painter, option, idx) + else: + # let's call the default paint method first; to paint the background (e.g. selection) + super().paint(painter, option, idx) + # and now paint on top of that + custom_data.paint(painter, option.rect) + + def helpEvent(self, evt: QHelpEvent, view: QAbstractItemView, option: QStyleOptionViewItem, idx: QModelIndex) -> bool: + custom_data = idx.data(MyTreeView.ROLE_CUSTOM_PAINT) + if custom_data is None: + return super().helpEvent(evt, view, option, idx) + else: + if evt.type() == QEvent.ToolTip: + if custom_data.show_tooltip(evt): + return True + return super().helpEvent(evt, view, option, idx) + + def sizeHint(self, option: QStyleOptionViewItem, idx: QModelIndex) -> QSize: + custom_data = idx.data(MyTreeView.ROLE_CUSTOM_PAINT) + if custom_data is None: + return super().sizeHint(option, idx) + else: + default_size = super().sizeHint(option, idx) + return custom_data.sizeHint(default_size) + class MyTreeView(QTreeView): ROLE_CLIPBOARD_DATA = Qt.UserRole + 100 + ROLE_CUSTOM_PAINT = Qt.UserRole + 101 filter_columns: Iterable[int]