From 44f661654dae2a8b849d974c552029af4a2e6c26 Mon Sep 17 00:00:00 2001 From: Michael Flaxman Date: Wed, 18 Nov 2020 11:35:02 -0600 Subject: [PATCH] better QR codes, still needs improvement --- README.md | 6 ++++-- multiwallet_gui/helper.py | 22 +++++++++++++------ multiwallet_gui/seedpicker.py | 1 + multiwallet_gui/send.py | 40 +++++++++++++++++++++++++++-------- setup.py | 2 +- 5 files changed, 53 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 3fcbe37..14c1c4e 100644 --- a/README.md +++ b/README.md @@ -50,14 +50,16 @@ python multiwallet_gui/app.py ``` ## Roadmap: +* Add support for choosing other checksum words * Add detailed TX view (not just summary) to UI -* Add QR code generation on send/receive +* Add QR encode on address verification +* Add QR gifs * Add units (sats/BTC) toggle * Test/release on multiple OS * Better form handling/validation * Support arbitrary paths * Add libsec -* Add webcam on receive/send +* Add webcam on receive/send for qrdecode * Sign binaries * Dark mode * Reproducible build diff --git a/multiwallet_gui/helper.py b/multiwallet_gui/helper.py index 4caeef5..d631cb0 100644 --- a/multiwallet_gui/helper.py +++ b/multiwallet_gui/helper.py @@ -52,10 +52,11 @@ def _msgbox_err(main_text=None, informative_text=None, detailed_text=None): class QRPopup(QDialog): - def __init__(self, window_title, qr_text): + def __init__(self, qr_text, window_title, window_height): super().__init__() self.setWindowTitle(window_title) + # self.height = window_height self.setMaximumHeight(16777215) self.setMaximumWidth(16777215) @@ -68,16 +69,19 @@ def __init__(self, window_title, qr_text): self.labelImage.setMaximumHeight(16777215) self.labelImage.setMaximumWidth(16777215) - self._set_pixmap() + self._set_pixmap(height_to_use=window_height * 0.9) self.vbox.addWidget(self.labelImage) self.setLayout(self.vbox) self.show() - def _set_pixmap(self): + def _set_pixmap(self, height_to_use=None): + if height_to_use is None: + height_to_use = self.height() * 0.9 + self.pixmap = create_qt_pixmap_qr(text=self.qr_text).scaledToHeight( - self.height() * 0.9 + height_to_use ) self.labelImage.setPixmap(self.pixmap) @@ -85,8 +89,14 @@ def resizeEvent(self, event): self.pixmap = self._set_pixmap() -def qr_dialog(qr_text, window_title): - dialog = QRPopup(qr_text=qr_text, window_title=strip_html(window_title)) +def qr_dialog(qwidget, qr_text, window_title): + # set to 90% of max size: https://stackoverflow.com/questions/35887237/current-screen-size-in-python3-with-pyqt5 + window_height = qwidget.screen().size().height() * 0.9 + dialog = QRPopup( + qr_text=qr_text, + window_title=strip_html(window_title), + window_height=window_height, + ) return dialog.exec_() diff --git a/multiwallet_gui/seedpicker.py b/multiwallet_gui/seedpicker.py index ef35e01..0a80830 100644 --- a/multiwallet_gui/seedpicker.py +++ b/multiwallet_gui/seedpicker.py @@ -204,6 +204,7 @@ def process_submit(self): def make_qr_popup(self): qr_dialog( + qwidget=self, qr_text=self.pubResultsROEdit.toPlainText(), window_title=self.pubResultsLabel.text(), ) diff --git a/multiwallet_gui/send.py b/multiwallet_gui/send.py index f1815ef..96c3f8d 100644 --- a/multiwallet_gui/send.py +++ b/multiwallet_gui/send.py @@ -5,7 +5,9 @@ BITCOIN_TESTNET_TOOLTIP, BITCOIN_MAINNET_TOOLTIP, _clean_submisission, + create_qr_icon, _msgbox_err, + qr_dialog, ) from PyQt5.QtWidgets import ( QVBoxLayout, @@ -44,10 +46,10 @@ class SendTab(QWidget): # FIXME (add support and UX for this) UNITS = "sats" - IS_TESTNET = True # No way to reliably infer this from the PSBT unfortunately :( def __init__(self): super().__init__() + vbox = QVBoxLayout() self.psbtLabel = QLabel( @@ -109,9 +111,14 @@ def __init__(self): self.psbtSignedLabel.setToolTip( "Signed version for your online computer to broadcast to the bitcoin network (once you have collected enough signatures)." ) - self.psbtSignedEdit = QPlainTextEdit("") - self.psbtSignedEdit.setReadOnly(True) - self.psbtSignedEdit.setHidden(True) + self.psbtSignedROEdit = QPlainTextEdit("") + self.psbtSignedROEdit.setReadOnly(True) + self.psbtSignedROEdit.setHidden(True) + + self.qrButton = QPushButton() + self.qrButton.setText("QR") + self.qrButton.setHidden(True) + self.qrButton.clicked.connect(self.make_qr_popup) for widget in ( self.psbtLabel, @@ -127,7 +134,8 @@ def __init__(self): self.psbtDecodedLabel, self.psbtDecodedROEdit, self.psbtSignedLabel, - self.psbtSignedEdit, + self.psbtSignedROEdit, + self.qrButton, ): vbox.addWidget(widget) @@ -139,6 +147,13 @@ def decode_psbt(self): def sign_psbt(self): return self.process_psbt(sign_tx=True) + def make_qr_popup(self): + return qr_dialog( + qwidget=self, + qr_text=self.psbtSignedROEdit.toPlainText(), + window_title=self.psbtSignedLabel.text(), + ) + def process_psbt(self, sign_tx=True): # Clear any previous submission in case of errors self.psbtDecodedLabel.setText("") @@ -146,8 +161,11 @@ def process_psbt(self, sign_tx=True): self.psbtDecodedROEdit.setHidden(True) self.psbtSignedLabel.setText("") - self.psbtSignedEdit.clear() - self.psbtSignedEdit.setHidden(True) + self.psbtSignedROEdit.clear() + self.psbtSignedROEdit.setHidden(True) + + self.qrButton.setHidden(True) + self.qrButton.setText("") # TODO: why setText and not hide? if self.infernetwork_button.isChecked(): @@ -433,8 +451,12 @@ def process_psbt(self, sign_tx=True): try: if psbt_obj.sign_with_private_keys(private_keys) is True: self.psbtSignedLabel.setText("Signed PSBT to Broadcast") - self.psbtSignedEdit.setHidden(False) - self.psbtSignedEdit.appendPlainText(psbt_obj.serialize_base64()) + self.psbtSignedROEdit.setHidden(False) + self.psbtSignedROEdit.appendPlainText(psbt_obj.serialize_base64()) + + self.qrButton.setHidden(False) + self.qrButton.setText("QR") + self.qrButton.setIcon(create_qr_icon()) else: return _msgbox_err( main_text="Transaction Not Signed", diff --git a/setup.py b/setup.py index a842264..156d09d 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name="multiwallet", - version="0.3.7", + version="0.3.8", author="Michael Flaxman", author_email="multiwallet@michaelflaxman.com", description="Stateless multisig bitcoin wallet",