diff --git a/electrum/gui/qt/address_dialog.py b/electrum/gui/qt/address_dialog.py index 86d7bddfd..a3688ace0 100644 --- a/electrum/gui/qt/address_dialog.py +++ b/electrum/gui/qt/address_dialog.py @@ -29,7 +29,7 @@ from PyQt5.QtWidgets import QVBoxLayout, QLabel from electrum.i18n import _ -from .util import WindowModalDialog, ButtonsLineEdit, ColorScheme, Buttons, CloseButton +from .util import WindowModalDialog, ButtonsLineEdit, ShowQRLineEdit, ColorScheme, Buttons, CloseButton from .history_list import HistoryList, HistoryModel from .qrtextedit import ShowQRTextEdit @@ -65,10 +65,7 @@ class AddressDialog(WindowModalDialog): self.setLayout(vbox) vbox.addWidget(QLabel(_("Address") + ":")) - self.addr_e = ButtonsLineEdit(self.address) - self.addr_e.addCopyButton() - self.addr_e.add_qr_show_button(config=self.config, title=_("Address")) - self.addr_e.setReadOnly(True) + self.addr_e = ShowQRLineEdit(self.address, self.config, title=_("Address")) vbox.addWidget(self.addr_e) try: @@ -78,9 +75,7 @@ class AddressDialog(WindowModalDialog): if pubkeys: vbox.addWidget(QLabel(_("Public keys") + ':')) for pubkey in pubkeys: - pubkey_e = ButtonsLineEdit(pubkey) - pubkey_e.addCopyButton() - pubkey_e.setReadOnly(True) + pubkey_e = ShowQRLineEdit(pubkey, self.config, title=_("Public Key")) vbox.addWidget(pubkey_e) redeem_script = self.wallet.get_redeem_script(address) diff --git a/electrum/gui/qt/channel_details.py b/electrum/gui/qt/channel_details.py index e6d624cef..357346b27 100644 --- a/electrum/gui/qt/channel_details.py +++ b/electrum/gui/qt/channel_details.py @@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, Sequence import PyQt5.QtGui as QtGui import PyQt5.QtWidgets as QtWidgets import PyQt5.QtCore as QtCore -from PyQt5.QtWidgets import QLabel, QLineEdit, QHBoxLayout +from PyQt5.QtWidgets import QLabel, QLineEdit, QHBoxLayout, QGridLayout from electrum.util import EventListener from electrum.i18n import _ @@ -14,7 +14,7 @@ from electrum.lnaddr import LnAddr, lndecode from electrum.bitcoin import COIN from electrum.wallet import Abstract_Wallet -from .util import Buttons, CloseButton, ButtonsLineEdit, MessageBoxMixin, WWLabel +from .util import Buttons, CloseButton, ShowQRLineEdit, MessageBoxMixin, WWLabel from .util import QtEventListener, qt_event_listener if TYPE_CHECKING: @@ -147,69 +147,69 @@ class ChannelDetailsDialog(QtWidgets.QDialog, MessageBoxMixin, QtEventListener): # add layouts vbox = QtWidgets.QVBoxLayout(self) - vbox.addWidget(QLabel(_('Remote Node ID:'))) - remote_id_e = ButtonsLineEdit(bh2u(chan.node_id)) - remote_id_e.addCopyButton() - remote_id_e.setReadOnly(True) - vbox.addWidget(remote_id_e) + form = QtWidgets.QFormLayout(None) + remote_id_e = ShowQRLineEdit(chan.node_id.hex(), self.window.config, title=_("Remote Node ID")) + form.addRow(QLabel(_('Remote Node') + ':'), remote_id_e) + channel_id_e = ShowQRLineEdit(chan.channel_id.hex(), self.window.config, title=_("Channel ID")) + form.addRow(QLabel(_('Channel ID') + ':'), channel_id_e) funding_label_text = f'{chan.funding_outpoint.txid}:{chan.funding_outpoint.output_index}' - vbox.addWidget(QLabel(_('Funding Outpoint:'))) - vbox.addWidget(LinkedLabel(funding_label_text, self.show_tx)) - + form.addRow(QLabel(_('Funding Outpoint') + ':'), LinkedLabel(funding_label_text, self.show_tx)) + form.addRow(QLabel(_('Short Channel ID') + ':'), QLabel(str(chan.short_channel_id))) + form.addRow(QLabel(_('State') + ':'), SelectableLabel(chan.get_state_for_GUI())) + self.capacity = self.format_sat(chan.get_capacity()) + form.addRow(QLabel(_('Capacity') + ':'), SelectableLabel(self.capacity)) + form.addRow(QLabel(_('Channel type:')), SelectableLabel(chan.storage['channel_type'].name_minimal)) + initiator = 'Local' if chan.constraints.is_initiator else 'Remote' + form.addRow(QLabel(_('Initiator:')), SelectableLabel(initiator)) + vbox.addLayout(form) hbox_stats = QHBoxLayout() - - # channel stats left column form_layout_left = QtWidgets.QFormLayout(None) - form_layout_left.addRow(_('Channel ID:'), WWLabel(f"{chan.channel_id.hex()} (Short: {chan.short_channel_id})")) - form_layout_left.addRow(_('State:'), SelectableLabel(chan.get_state_for_GUI())) - self.initiator = 'Local' if chan.constraints.is_initiator else 'Remote' - form_layout_left.addRow(_('Initiator:'), SelectableLabel(self.initiator)) - self.capacity = self.format_sat(chan.get_capacity()) - form_layout_left.addRow(_('Capacity:'), SelectableLabel(self.capacity)) + form_layout_right = QtWidgets.QFormLayout(None) + self.local_balance_label = SelectableLabel() + self.remote_balance_label = SelectableLabel() + form_layout_left.addRow(_('Local balance') + ':', self.local_balance_label) + form_layout_right.addRow(_('Remote balance') + ':', self.remote_balance_label) self.can_send_label = SelectableLabel() self.can_receive_label = SelectableLabel() - form_layout_left.addRow(_('Can send:'), self.can_send_label) - form_layout_left.addRow(_('Can receive:'), self.can_receive_label) + form_layout_left.addRow(_('Can send') + ':', self.can_send_label) + form_layout_right.addRow(_('Can receive') + ':', self.can_receive_label) + local_reserve_label = SelectableLabel("{}".format( + self.format_sat(chan.config[LOCAL].reserve_sat), + )) + remote_reserve_label = SelectableLabel("{}".format( + self.format_sat(chan.config[REMOTE].reserve_sat), + )) + form_layout_left.addRow(_('Local reserve') + ':', local_reserve_label) + form_layout_right.addRow(_('Remote reserve' + ':'), remote_reserve_label) #self.htlc_minimum_msat = SelectableLabel(str(chan.config[REMOTE].htlc_minimum_msat)) #form_layout_left.addRow(_('Minimum HTLC value accepted by peer (mSAT):'), self.htlc_minimum_msat) #self.max_htlcs = SelectableLabel(str(chan.config[REMOTE].max_accepted_htlcs)) #form_layout_left.addRow(_('Maximum number of concurrent HTLCs accepted by peer:'), self.max_htlcs) #self.max_htlc_value = SelectableLabel(self.format_sat(chan.config[REMOTE].max_htlc_value_in_flight_msat / 1000)) #form_layout_left.addRow(_('Maximum value of in-flight HTLCs accepted by peer:'), self.max_htlc_value) - dust_limit_label = SelectableLabel("{}, {}".format( - self.format_sat(chan.config[REMOTE].dust_limit_sat), + local_dust_limit_label = SelectableLabel("{}".format( self.format_sat(chan.config[LOCAL].dust_limit_sat), )) - form_layout_left.addRow(_('Dust limit:'), dust_limit_label) - chan_reserve_label = SelectableLabel("{}, {}".format( - self.format_sat(chan.config[REMOTE].reserve_sat), - self.format_sat(chan.config[LOCAL].reserve_sat), + remote_dust_limit_label = SelectableLabel("{}".format( + self.format_sat(chan.config[REMOTE].dust_limit_sat), )) - form_layout_left.addRow(_('Channel reserve:'), chan_reserve_label) - form_layout_left.addRow(_('Channel type:'), SelectableLabel(chan.storage['channel_type'].name_minimal)) + form_layout_left.addRow(_('Local dust limit') + ':', local_dust_limit_label) + form_layout_right.addRow(_('Remote dust limit') + ':', remote_dust_limit_label) + self.received_label = SelectableLabel() + self.sent_label = SelectableLabel() + form_layout_left.addRow(_('Total sent') + ':', self.sent_label) + form_layout_right.addRow(_('Total received') + ':', self.received_label) + # channel stats left column hbox_stats.addLayout(form_layout_left, 50) - # vertical line separator line_separator = QtWidgets.QFrame() line_separator.setFrameShape(QtWidgets.QFrame.VLine) line_separator.setFrameShadow(QtWidgets.QFrame.Sunken) line_separator.setLineWidth(1) hbox_stats.addWidget(line_separator) - # channel stats right column - form_layout_right = QtWidgets.QFormLayout(None) - self.local_balance_label = SelectableLabel() - self.remote_balance_label = SelectableLabel() - form_layout_right.addRow(_('Local balance:'), self.local_balance_label) - form_layout_right.addRow(_('Remote balance:'), self.remote_balance_label) - self.received_label = SelectableLabel() - self.sent_label = SelectableLabel() - form_layout_right.addRow(_('Total received so far:'), self.received_label) - form_layout_right.addRow(_('Total sent so far:'), self.sent_label) hbox_stats.addLayout(form_layout_right, 50) - vbox.addLayout(hbox_stats) - # add htlc tree view to vbox (wouldn't scale correctly in QFormLayout) vbox.addWidget(QLabel(_('Payments (HTLCs):'))) w = QtWidgets.QTreeView(self) diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py index c94eabfa4..afc666015 100644 --- a/electrum/gui/qt/main_window.py +++ b/electrum/gui/qt/main_window.py @@ -89,7 +89,7 @@ from .util import (read_QIcon, ColorScheme, text_dialog, icon_path, WaitingDialo filename_field, address_field, char_width_in_lineedit, webopen, TRANSACTION_FILE_EXTENSION_FILTER_ANY, MONOSPACE_FONT, getOpenFileName, getSaveFileName, BlockingWaitingDialog) -from .util import ButtonsLineEdit +from .util import ButtonsLineEdit, ShowQRLineEdit from .util import QtEventListener, qt_event_listener, event_listener from .installwizard import WIF_HELP_TEXT from .history_list import HistoryList, HistoryModel @@ -1449,11 +1449,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener): d = WindowModalDialog(self, _("Lightning Invoice")) vbox = QVBoxLayout(d) grid = QGridLayout() - pubkey_e = ButtonsLineEdit(lnaddr.pubkey.serialize().hex()) - pubkey_e.setFont(QFont(MONOSPACE_FONT)) - pubkey_e.add_qr_show_button(config=self.config, title=_("Public Key")) - pubkey_e.addCopyButton() - pubkey_e.setReadOnly(True) + pubkey_e = ShowQRLineEdit(lnaddr.pubkey.serialize().hex(), self.config, title=_("Public Key")) pubkey_e.setMinimumWidth(700) grid.addWidget(QLabel(_("Public Key") + ':'), 0, 0) grid.addWidget(pubkey_e, 0, 1) @@ -1469,11 +1465,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener): grid.addWidget(QLabel(format_time(invoice.time + invoice.exp)), 4, 1) grid.addWidget(QLabel(_('Features') + ':'), 5, 0) grid.addWidget(QLabel('\n'.join(lnaddr.get_features().get_names())), 5, 1) - payhash_e = ButtonsLineEdit(lnaddr.paymenthash.hex()) - payhash_e.setFont(QFont(MONOSPACE_FONT)) - payhash_e.add_qr_show_button(config=self.config, title=_("Payment Hash")) - payhash_e.addCopyButton() - payhash_e.setReadOnly(True) + payhash_e = ShowQRLineEdit(lnaddr.paymenthash.hex(), self.config, title=_("Payment Hash")) grid.addWidget(QLabel(_("Payment Hash") + ':'), 6, 0) grid.addWidget(payhash_e, 6, 1) invoice_e = ShowQRTextEdit(config=self.config) @@ -1777,11 +1769,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener): grid.addWidget(HelpButton(msg), 5, 3) grid.addWidget(WWLabel(_('Lightning Node ID:')), 7, 0) nodeid_text = self.wallet.lnworker.node_keypair.pubkey.hex() - nodeid_e = ButtonsLineEdit(nodeid_text) - nodeid_e.add_qr_show_button(config=self.config, title=_("Node ID")) - nodeid_e.addCopyButton() - nodeid_e.setReadOnly(True) - nodeid_e.setFont(QFont(MONOSPACE_FONT)) + nodeid_e = ShowQRLineEdit(nodeid_text, self.config, title=_("Node ID")) grid.addWidget(nodeid_e, 8, 0, 1, 4) else: if self.wallet.can_have_lightning(): diff --git a/electrum/gui/qt/transaction_dialog.py b/electrum/gui/qt/transaction_dialog.py index 64c5695a0..cb659ca44 100644 --- a/electrum/gui/qt/transaction_dialog.py +++ b/electrum/gui/qt/transaction_dialog.py @@ -49,7 +49,7 @@ from electrum.transaction import SerializationError, Transaction, PartialTransac from electrum.logging import get_logger from .util import (MessageBoxMixin, read_QIcon, Buttons, icon_path, - MONOSPACE_FONT, ColorScheme, ButtonsLineEdit, text_dialog, + MONOSPACE_FONT, ColorScheme, ButtonsLineEdit, ShowQRLineEdit, text_dialog, char_width_in_lineedit, TRANSACTION_FILE_EXTENSION_FILTER_SEPARATE, TRANSACTION_FILE_EXTENSION_FILTER_ONLY_COMPLETE_TX, TRANSACTION_FILE_EXTENSION_FILTER_ONLY_PARTIAL_TX, @@ -121,9 +121,7 @@ class BaseTxDialog(QDialog, MessageBoxMixin): self.setLayout(vbox) vbox.addWidget(QLabel(_("Transaction ID:"))) - self.tx_hash_e = ButtonsLineEdit() - self.tx_hash_e.add_qr_show_button(config=self.config, title='Transaction ID') - self.tx_hash_e.setReadOnly(True) + self.tx_hash_e = ShowQRLineEdit('', self.config, title='Transaction ID') vbox.addWidget(self.tx_hash_e) self.add_tx_stats(vbox) diff --git a/electrum/gui/qt/util.py b/electrum/gui/qt/util.py index 5beba3946..313a74235 100644 --- a/electrum/gui/qt/util.py +++ b/electrum/gui/qt/util.py @@ -1143,6 +1143,14 @@ class ButtonsLineEdit(OverlayControlMixin, QLineEdit): QLineEdit.__init__(self, text) OverlayControlMixin.__init__(self, middle=True) +class ShowQRLineEdit(ButtonsLineEdit): + """ read-only line with qr and copy buttons """ + def __init__(self, text: str, config, title=None): + ButtonsLineEdit.__init__(self, text) + self.setReadOnly(True) + self.setFont(QFont(MONOSPACE_FONT)) + self.add_qr_show_button(config=config, title=title) + self.addCopyButton() class ButtonsTextEdit(OverlayControlMixin, QPlainTextEdit): def __init__(self, text=None):