|
|
|
|
@ -73,18 +73,16 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|
|
|
|
buttons.addWidget(self.create_invoice_button) |
|
|
|
|
grid.addLayout(buttons, 4, 0, 1, -1) |
|
|
|
|
|
|
|
|
|
self.receive_address_e = QTextEdit() |
|
|
|
|
self.receive_address_help_text = WWLabel('') |
|
|
|
|
vbox = QVBoxLayout() |
|
|
|
|
vbox.addWidget(self.receive_address_help_text) |
|
|
|
|
self.receive_address_help = FramedWidget() |
|
|
|
|
self.receive_address_help.setVisible(False) |
|
|
|
|
self.receive_address_help.setLayout(vbox) |
|
|
|
|
|
|
|
|
|
self.receive_URI_e = QTextEdit() |
|
|
|
|
self.receive_URI_help = WWLabel('') |
|
|
|
|
self.receive_lightning_e = QTextEdit() |
|
|
|
|
self.receive_lightning_help_text = WWLabel('') |
|
|
|
|
self.receive_e = QTextEdit() |
|
|
|
|
self.receive_e.setFont(QFont(MONOSPACE_FONT)) |
|
|
|
|
self.receive_e.setReadOnly(True) |
|
|
|
|
self.receive_e.setContextMenuPolicy(Qt.NoContextMenu) |
|
|
|
|
self.receive_e.setTextInteractionFlags(Qt.NoTextInteraction) |
|
|
|
|
self.receive_e.textChanged.connect(self.update_receive_widgets) |
|
|
|
|
|
|
|
|
|
self.receive_qr = QRCodeWidget(manual_size=True) |
|
|
|
|
|
|
|
|
|
self.receive_help_text = WWLabel('') |
|
|
|
|
self.receive_rebalance_button = QPushButton('Rebalance') |
|
|
|
|
self.receive_rebalance_button.suggestion = None |
|
|
|
|
def on_receive_rebalance(): |
|
|
|
|
@ -103,44 +101,19 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|
|
|
|
buttons.addWidget(self.receive_rebalance_button) |
|
|
|
|
buttons.addWidget(self.receive_swap_button) |
|
|
|
|
vbox = QVBoxLayout() |
|
|
|
|
vbox.addWidget(self.receive_lightning_help_text) |
|
|
|
|
vbox.addWidget(self.receive_help_text) |
|
|
|
|
vbox.addLayout(buttons) |
|
|
|
|
self.receive_lightning_help = FramedWidget() |
|
|
|
|
self.receive_lightning_help.setVisible(False) |
|
|
|
|
self.receive_lightning_help.setLayout(vbox) |
|
|
|
|
self.receive_address_qr = QRCodeWidget(manual_size=True) |
|
|
|
|
self.receive_URI_qr = QRCodeWidget(manual_size=True) |
|
|
|
|
self.receive_lightning_qr = QRCodeWidget(manual_size=True) |
|
|
|
|
|
|
|
|
|
for e in [self.receive_address_e, self.receive_URI_e, self.receive_lightning_e]: |
|
|
|
|
e.setFont(QFont(MONOSPACE_FONT)) |
|
|
|
|
e.setReadOnly(True) |
|
|
|
|
e.setContextMenuPolicy(Qt.NoContextMenu) |
|
|
|
|
e.setTextInteractionFlags(Qt.NoTextInteraction) |
|
|
|
|
|
|
|
|
|
self.receive_lightning_e.textChanged.connect(self.update_receive_widgets) |
|
|
|
|
|
|
|
|
|
self.receive_address_widget = ReceiveTabWidget(self, |
|
|
|
|
self.receive_address_e, self.receive_address_qr, self.receive_address_help) |
|
|
|
|
self.receive_URI_widget = ReceiveTabWidget(self, |
|
|
|
|
self.receive_URI_e, self.receive_URI_qr, self.receive_URI_help) |
|
|
|
|
self.receive_lightning_widget = ReceiveTabWidget(self, |
|
|
|
|
self.receive_lightning_e, self.receive_lightning_qr, self.receive_lightning_help) |
|
|
|
|
|
|
|
|
|
from .util import VTabWidget |
|
|
|
|
self.receive_tabs = VTabWidget() |
|
|
|
|
self.receive_tabs.setMinimumHeight(ReceiveTabWidget.min_size.height()) |
|
|
|
|
|
|
|
|
|
#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')) |
|
|
|
|
self.receive_tabs.setCurrentIndex(self.config.get('receive_tabs_index', 0)) |
|
|
|
|
self.receive_tabs.currentChanged.connect(self.on_tab_changed) |
|
|
|
|
receive_tabs_sp = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) |
|
|
|
|
receive_tabs_sp.setRetainSizeWhenHidden(True) |
|
|
|
|
self.receive_tabs.setSizePolicy(receive_tabs_sp) |
|
|
|
|
self.receive_tabs.setVisible(False) |
|
|
|
|
self.receive_help_widget = FramedWidget() |
|
|
|
|
self.receive_help_widget.setVisible(False) |
|
|
|
|
self.receive_help_widget.setLayout(vbox) |
|
|
|
|
|
|
|
|
|
self.receive_widget = ReceiveWidget( |
|
|
|
|
self, self.receive_e, self.receive_qr, self.receive_help_widget) |
|
|
|
|
|
|
|
|
|
receive_widget_sp = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) |
|
|
|
|
receive_widget_sp.setRetainSizeWhenHidden(True) |
|
|
|
|
self.receive_widget.setSizePolicy(receive_widget_sp) |
|
|
|
|
self.receive_widget.setVisible(False) |
|
|
|
|
|
|
|
|
|
self.receive_requests_label = QLabel(_('Requests')) |
|
|
|
|
# with QDarkStyle, this label may partially cover the qrcode widget. |
|
|
|
|
@ -150,12 +123,20 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|
|
|
|
self.request_list = RequestList(self) |
|
|
|
|
# toolbar |
|
|
|
|
self.toolbar, menu = self.request_list.create_toolbar_with_menu('') |
|
|
|
|
|
|
|
|
|
self.toggle_qr_button = QPushButton('') |
|
|
|
|
self.toggle_qr_button.setIcon(read_QIcon('qrcode.png')) |
|
|
|
|
self.toggle_qr_button.setToolTip(_('Switch between text and QR code view')) |
|
|
|
|
self.toggle_qr_button.clicked.connect(self.toggle_receive_qr) |
|
|
|
|
self.toggle_qr_button.setEnabled(False) |
|
|
|
|
self.toolbar.insertWidget(2, self.toggle_qr_button) |
|
|
|
|
|
|
|
|
|
self.toggle_view_button = QPushButton('') |
|
|
|
|
self.toggle_view_button.setToolTip(_('switch between view')) |
|
|
|
|
self.toggle_view_button.clicked.connect(self.toggle_view) |
|
|
|
|
self.toggle_view_button.setEnabled(False) |
|
|
|
|
self.update_view_button() |
|
|
|
|
self.toolbar.insertWidget(2, self.toggle_view_button) |
|
|
|
|
# menu |
|
|
|
|
menu.addConfig( |
|
|
|
|
_('Add on-chain fallback to lightning requests'), 'bolt11_fallback', True, |
|
|
|
|
@ -177,7 +158,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|
|
|
|
hbox = QHBoxLayout() |
|
|
|
|
hbox.addLayout(vbox_g) |
|
|
|
|
hbox.addStretch() |
|
|
|
|
hbox.addWidget(self.receive_tabs) |
|
|
|
|
hbox.addWidget(self.receive_widget) |
|
|
|
|
|
|
|
|
|
self.searchable_list = self.request_list |
|
|
|
|
vbox = QVBoxLayout(self) |
|
|
|
|
@ -220,17 +201,33 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|
|
|
|
self.wallet.lnworker.clear_invoices_cache() |
|
|
|
|
self.update_current_request() |
|
|
|
|
|
|
|
|
|
def on_tab_changed(self, i): |
|
|
|
|
def update_view_button(self): |
|
|
|
|
i = self.config.get('receive_tabs_index', 0) |
|
|
|
|
if i == 0: |
|
|
|
|
icon, text = read_QIcon("link.png"), _('Bitcoin URI') |
|
|
|
|
elif i == 1: |
|
|
|
|
icon, text = read_QIcon("bitcoin.png"), _('Address') |
|
|
|
|
elif i == 2: |
|
|
|
|
icon, text = read_QIcon("lightning.png"), _('Lightning') |
|
|
|
|
self.toggle_view_button.setText(text) |
|
|
|
|
self.toggle_view_button.setIcon(icon) |
|
|
|
|
|
|
|
|
|
def toggle_view(self): |
|
|
|
|
i = self.config.get('receive_tabs_index', 0) |
|
|
|
|
i = (i + 1) % (3 if self.wallet.has_lightning() else 2) |
|
|
|
|
self.config.set_key('receive_tabs_index', i) |
|
|
|
|
title, data = self.get_tab_data(i) |
|
|
|
|
self.update_current_request() |
|
|
|
|
self.update_view_button() |
|
|
|
|
|
|
|
|
|
def on_tab_changed(self): |
|
|
|
|
text, data, help_text, title = self.get_tab_data() |
|
|
|
|
self.window.do_copy(data, title=title) |
|
|
|
|
self.update_receive_qr_window() |
|
|
|
|
|
|
|
|
|
def do_copy(self, e): |
|
|
|
|
if e.button() != Qt.LeftButton: |
|
|
|
|
return |
|
|
|
|
i = self.receive_tabs.currentIndex() |
|
|
|
|
title, data = self.get_tab_data(i) |
|
|
|
|
text, data, help_text, title = self.get_tab_data() |
|
|
|
|
self.window.do_copy(data, title=title) |
|
|
|
|
|
|
|
|
|
def toggle_receive_qr(self): |
|
|
|
|
@ -240,75 +237,59 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|
|
|
|
|
|
|
|
|
def update_receive_widgets(self): |
|
|
|
|
b = self.config.get('receive_qr_visible', False) |
|
|
|
|
self.receive_URI_widget.update_visibility(b) |
|
|
|
|
self.receive_address_widget.update_visibility(b) |
|
|
|
|
self.receive_lightning_widget.update_visibility(b) |
|
|
|
|
self.receive_widget.update_visibility(b) |
|
|
|
|
|
|
|
|
|
def update_current_request(self): |
|
|
|
|
key = self.request_list.get_current_key() |
|
|
|
|
req = self.wallet.get_request(key) if key else None |
|
|
|
|
if req is None: |
|
|
|
|
self.receive_URI_e.setText('') |
|
|
|
|
self.receive_lightning_e.setText('') |
|
|
|
|
self.receive_address_e.setText('') |
|
|
|
|
self.receive_e.setText('') |
|
|
|
|
return |
|
|
|
|
help_texts = self.wallet.get_help_texts_for_receive_request(req) |
|
|
|
|
addr = (req.get_address() or '') if not help_texts.address_is_error else '' |
|
|
|
|
URI = (self.wallet.get_request_URI(req) or '') if not help_texts.URI_is_error else '' |
|
|
|
|
lnaddr = self.wallet.get_bolt11_invoice(req) if not help_texts.ln_is_error else '' |
|
|
|
|
address_help = help_texts.address_help |
|
|
|
|
URI_help = help_texts.URI_help |
|
|
|
|
ln_help = help_texts.ln_help |
|
|
|
|
self.addr = (req.get_address() or '') if not help_texts.address_is_error else '' |
|
|
|
|
self.URI = (self.wallet.get_request_URI(req) or '') if not help_texts.URI_is_error else '' |
|
|
|
|
self.lnaddr = self.wallet.get_bolt11_invoice(req) if not help_texts.ln_is_error else '' |
|
|
|
|
self.address_help = help_texts.address_help |
|
|
|
|
self.URI_help = help_texts.URI_help |
|
|
|
|
self.ln_help = help_texts.ln_help |
|
|
|
|
can_rebalance = help_texts.can_rebalance() |
|
|
|
|
can_swap = help_texts.can_swap() |
|
|
|
|
self.receive_rebalance_button.suggestion = help_texts.ln_rebalance_suggestion |
|
|
|
|
self.receive_swap_button.suggestion = help_texts.ln_swap_suggestion |
|
|
|
|
|
|
|
|
|
self.receive_rebalance_button.setVisible(can_rebalance) |
|
|
|
|
self.receive_swap_button.setVisible(can_swap) |
|
|
|
|
self.receive_rebalance_button.setEnabled(can_rebalance and self.window.num_tasks() == 0) |
|
|
|
|
self.receive_swap_button.setEnabled(can_swap and self.window.num_tasks() == 0) |
|
|
|
|
icon_name = "lightning.png" if lnaddr else "lightning_disconnected.png" |
|
|
|
|
self.receive_tabs.setTabIcon(2, read_QIcon(icon_name)) |
|
|
|
|
# encode lightning invoices as uppercase so QR encoding can use |
|
|
|
|
# alphanumeric mode; resulting in smaller QR codes |
|
|
|
|
self.receive_address_e.setText(addr) |
|
|
|
|
self.receive_address_qr.setData(addr) |
|
|
|
|
self.receive_address_help_text.setText(address_help) |
|
|
|
|
self.receive_URI_e.setText(URI) |
|
|
|
|
self.receive_URI_qr.setData(URI) |
|
|
|
|
self.receive_URI_help.setText(URI_help) |
|
|
|
|
self.receive_lightning_e.setText(lnaddr) # TODO maybe prepend "lightning:" ?? |
|
|
|
|
self.receive_lightning_help_text.setText(ln_help) |
|
|
|
|
self.receive_lightning_qr.setData(lnaddr.upper()) |
|
|
|
|
def update_warnings(text_e, qr_e, warning_text): |
|
|
|
|
for w in [text_e, qr_e]: |
|
|
|
|
w.setEnabled(bool(text_e.toPlainText()) and not warning_text) |
|
|
|
|
w.setToolTip(warning_text) |
|
|
|
|
update_warnings(self.receive_address_e, self.receive_address_qr, address_help) |
|
|
|
|
update_warnings(self.receive_URI_e, self.receive_URI_qr, URI_help) |
|
|
|
|
update_warnings(self.receive_lightning_e, self.receive_lightning_qr, ln_help) |
|
|
|
|
text, data, help_text, title = self.get_tab_data() |
|
|
|
|
self.receive_e.setText(text) |
|
|
|
|
self.receive_qr.setData(data) |
|
|
|
|
self.receive_help_text.setText(help_text) |
|
|
|
|
for w in [self.receive_e, self.receive_qr]: |
|
|
|
|
w.setEnabled(bool(text) and not help_text) |
|
|
|
|
w.setToolTip(help_text) |
|
|
|
|
# macOS hack (similar to #4777) |
|
|
|
|
self.receive_lightning_e.repaint() |
|
|
|
|
self.receive_URI_e.repaint() |
|
|
|
|
self.receive_address_e.repaint() |
|
|
|
|
self.receive_e.repaint() |
|
|
|
|
# always show |
|
|
|
|
self.receive_tabs.setVisible(True) |
|
|
|
|
self.receive_widget.setVisible(True) |
|
|
|
|
self.toggle_qr_button.setEnabled(True) |
|
|
|
|
self.toggle_view_button.setEnabled(True) |
|
|
|
|
self.update_receive_qr_window() |
|
|
|
|
|
|
|
|
|
def get_tab_data(self, i): |
|
|
|
|
def get_tab_data(self): |
|
|
|
|
i = self.config.get('receive_tabs_index', 0) |
|
|
|
|
if i == 0: |
|
|
|
|
return _('Bitcoin URI'), self.receive_URI_e.toPlainText() |
|
|
|
|
out = self.URI, self.URI, self.URI_help, _('Bitcoin URI') |
|
|
|
|
elif i == 1: |
|
|
|
|
return _('Address'), self.receive_address_e.toPlainText() |
|
|
|
|
else: |
|
|
|
|
return _('Lightning Request'), self.receive_lightning_e.toPlainText() |
|
|
|
|
out = self.addr, self.addr, self.address_help, _('Address') |
|
|
|
|
elif i == 2: |
|
|
|
|
# encode lightning invoices as uppercase so QR encoding can use |
|
|
|
|
# alphanumeric mode; resulting in smaller QR codes |
|
|
|
|
out = self.lnaddr, self.lnaddr.upper(), self.ln_help, _('Lightning Request') |
|
|
|
|
return out |
|
|
|
|
|
|
|
|
|
def update_receive_qr_window(self): |
|
|
|
|
if self.window.qr_window and self.window.qr_window.isVisible(): |
|
|
|
|
i = self.receive_tabs.currentIndex() |
|
|
|
|
title, data = self.get_tab_data(i) |
|
|
|
|
text, data, help_text, title = self.get_tab_data() |
|
|
|
|
if i == 2: |
|
|
|
|
data = data.upper() |
|
|
|
|
self.window.qr_window.qrw.setData(data) |
|
|
|
|
@ -347,7 +328,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|
|
|
|
self.receive_amount_e.setText('') |
|
|
|
|
self.receive_message_e.setText('') |
|
|
|
|
# copy current tab to clipboard |
|
|
|
|
self.on_tab_changed(self.receive_tabs.currentIndex()) |
|
|
|
|
self.on_tab_changed() |
|
|
|
|
|
|
|
|
|
def get_bitcoin_address_for_request(self, amount) -> Optional[str]: |
|
|
|
|
addr = self.wallet.get_unused_address() |
|
|
|
|
@ -369,25 +350,25 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|
|
|
|
return addr |
|
|
|
|
|
|
|
|
|
def do_clear(self): |
|
|
|
|
self.receive_address_e.setText('') |
|
|
|
|
self.receive_URI_e.setText('') |
|
|
|
|
self.receive_lightning_e.setText('') |
|
|
|
|
self.receive_tabs.setVisible(False) |
|
|
|
|
self.receive_e.setText('') |
|
|
|
|
self.receive_widget.setVisible(False) |
|
|
|
|
self.toggle_qr_button.setEnabled(False) |
|
|
|
|
self.toggle_view_button.setEnabled(False) |
|
|
|
|
self.receive_message_e.setText('') |
|
|
|
|
self.receive_amount_e.setAmount(None) |
|
|
|
|
self.request_list.clearSelection() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ReceiveTabWidget(QWidget): |
|
|
|
|
class ReceiveWidget(QWidget): |
|
|
|
|
min_size = QSize(200, 200) |
|
|
|
|
|
|
|
|
|
def __init__(self, receive_tab: 'ReceiveTab', textedit: QWidget, qr: QWidget, help_widget: QWidget): |
|
|
|
|
QWidget.__init__(self) |
|
|
|
|
self.textedit = textedit |
|
|
|
|
self.qr = qr |
|
|
|
|
self.help_widget = help_widget |
|
|
|
|
QWidget.__init__(self) |
|
|
|
|
self.setMinimumSize(self.min_size) |
|
|
|
|
for w in [textedit, qr, help_widget]: |
|
|
|
|
w.setMinimumSize(self.min_size) |
|
|
|
|
|
|
|
|
|
@ -416,6 +397,12 @@ class ReceiveTabWidget(QWidget):
|
|
|
|
|
self.textedit.setVisible(False) |
|
|
|
|
self.qr.setVisible(False) |
|
|
|
|
|
|
|
|
|
def resizeEvent(self, e): |
|
|
|
|
# keep square aspect ratio when resized |
|
|
|
|
size = e.size() |
|
|
|
|
w = size.height() |
|
|
|
|
self.setFixedWidth(w) |
|
|
|
|
return super().resizeEvent(e) |
|
|
|
|
|
|
|
|
|
class FramedWidget(QFrame): |
|
|
|
|
def __init__(self): |
|
|
|
|
|