tCombine QTHandlers for KeepKey and Trezor - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit 7b5f3884fadcf1938bec8f60049b1f4101cb8b14 DIR parent 39c1893a747c7e209aad80f551a7eb08e048c4d4 HTML Author: Neil Booth <kyuupichan@gmail.com> Date: Sat, 26 Dec 2015 17:40:12 +0900 Combine QTHandlers for KeepKey and Trezor Again they do the same thing, so share the code Diffstat: M plugins/keepkey/qt.py | 97 ++++--------------------------- M plugins/trezor/qt.py | 84 +++---------------------------- A plugins/trezor/qt_generic.py | 91 +++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 165 deletions(-) --- DIR diff --git a/plugins/keepkey/qt.py b/plugins/keepkey/qt.py t@@ -2,14 +2,20 @@ from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL, QGridLayout, QInputDialog, QPu import PyQt4.QtCore as QtCore from electrum_gui.qt.util import * from electrum_gui.qt.main_window import StatusBarButton, ElectrumWindow -from electrum_gui.qt.installwizard import InstallWizard -from keepkeylib.qt.pinmatrix import PinMatrixWidget from functools import partial +import unicodedata -from keepkey import KeepKeyPlugin, KeepKeyWallet -from electrum.plugins import hook from electrum.i18n import _ +from electrum.plugins import hook + +from plugins.trezor.qt_generic import QtHandler +from keepkeylib.qt.pinmatrix import PinMatrixWidget +from keepkey import KeepKeyPlugin, KeepKeyWallet + +class KeepKeyQtHandler(QtHandler): + device = 'KeepKey' + pin_matrix_widget_class = PinMatrixWidget class Plugin(KeepKeyPlugin): t@@ -90,86 +96,3 @@ class Plugin(KeepKeyPlugin): layout.addWidget(current_label_label,3,0) layout.addWidget(change_label_button,3,1) d.exec_() - - -class KeepKeyQtHandler: - - def __init__(self, win): - self.win = win - self.win.connect(win, SIGNAL('keepkey_done'), self.dialog_stop) - self.win.connect(win, SIGNAL('message_dialog'), self.message_dialog) - self.win.connect(win, SIGNAL('pin_dialog'), self.pin_dialog) - self.win.connect(win, SIGNAL('passphrase_dialog'), self.passphrase_dialog) - self.done = threading.Event() - self.d = None - - def stop(self): - self.win.emit(SIGNAL('keepkey_done')) - - def show_message(self, msg_code, msg, client): - self.messsage_code = msg_code - self.message = msg - self.client = client - self.win.emit(SIGNAL('message_dialog')) - - def get_pin(self, msg): - self.done.clear() - self.message = msg - self.win.emit(SIGNAL('pin_dialog')) - self.done.wait() - return self.response - - def get_passphrase(self, msg): - self.done.clear() - self.message = msg - self.win.emit(SIGNAL('passphrase_dialog')) - self.done.wait() - return self.passphrase - - def pin_dialog(self): - d = WindowModalDialog(self.win, _("Enter PIN")) - matrix = PinMatrixWidget() - vbox = QVBoxLayout() - vbox.addWidget(QLabel(self.message)) - vbox.addWidget(matrix) - vbox.addLayout(Buttons(CancelButton(d), OkButton(d))) - d.setLayout(vbox) - if not d.exec_(): - self.response = None - self.response = str(matrix.get_value()) - self.done.set() - - def passphrase_dialog(self): - if type(self.win) is ElectrumWindow: - passphrase = self.win.password_dialog(_("Please enter your KeepKey passphrase")) - self.passphrase = unicodedata.normalize('NFKD', unicode(passphrase)) if passphrase else '' - else: - assert type(self.win) is InstallWizard - from electrum_gui.qt.password_dialog import PasswordDialog - d = PasswordDialog(self.win, None, None, self.message, False) - confirmed, p, passphrase = d.run() - if not confirmed: - self.win.show_critical(_("Password request canceled")) - self.passphrase = None - else: - self.passphrase = unicodedata.normalize('NFKD', unicode(passphrase)) if passphrase else '' - self.done.set() - - def message_dialog(self): - # Called more than once during signing, to confirm output and fee - self.dialog_stop() - self.d = WindowModalDialog(self.win, _('Please Check KeepKey Device')) - l = QLabel(self.message) - vbox = QVBoxLayout(self.d) - vbox.addWidget(l) - - if self.messsage_code in (3, 8): - vbox.addLayout(Buttons(CancelButton(self.d))) - self.d.connect(self.d, SIGNAL('rejected()'), self.client.cancel) - - self.d.show() - - def dialog_stop(self): - if self.d: - self.d.hide() - self.d = None DIR diff --git a/plugins/trezor/qt.py b/plugins/trezor/qt.py t@@ -2,92 +2,20 @@ from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL, QGridLayout, QInputDialog, QPu import PyQt4.QtCore as QtCore from electrum_gui.qt.util import * from electrum_gui.qt.main_window import StatusBarButton, ElectrumWindow -from electrum_gui.qt.installwizard import InstallWizard -from trezorlib.qt.pinmatrix import PinMatrixWidget - from functools import partial import unicodedata from electrum.i18n import _ -from electrum.plugins import hook, always_hook, run_hook +from electrum.plugins import hook +from plugins.trezor.qt_generic import QtHandler from trezor import TrezorPlugin, TrezorWallet +from trezorlib.qt.pinmatrix import PinMatrixWidget -class TrezorQtHandler: - - def __init__(self, win): - self.win = win - self.win.connect(win, SIGNAL('trezor_done'), self.dialog_stop) - self.win.connect(win, SIGNAL('message_dialog'), self.message_dialog) - self.win.connect(win, SIGNAL('pin_dialog'), self.pin_dialog) - self.win.connect(win, SIGNAL('passphrase_dialog'), self.passphrase_dialog) - self.done = threading.Event() - self.d = None - - def stop(self): - self.win.emit(SIGNAL('trezor_done')) - - def show_message(self, msg): - self.message = msg - self.win.emit(SIGNAL('message_dialog')) - - def get_pin(self, msg): - self.done.clear() - self.message = msg - self.win.emit(SIGNAL('pin_dialog')) - self.done.wait() - return self.response - - def get_passphrase(self, msg): - self.done.clear() - self.message = msg - self.win.emit(SIGNAL('passphrase_dialog')) - self.done.wait() - return self.passphrase - - def pin_dialog(self): - d = WindowModalDialog(self.win, _("Enter PIN")) - matrix = PinMatrixWidget() - vbox = QVBoxLayout() - vbox.addWidget(QLabel(self.message)) - vbox.addWidget(matrix) - vbox.addLayout(Buttons(CancelButton(d), OkButton(d))) - d.setLayout(vbox) - if not d.exec_(): - self.response = None - self.response = str(matrix.get_value()) - self.done.set() - - def passphrase_dialog(self): - if type(self.win) is ElectrumWindow: - passphrase = self.win.password_dialog(_("Please enter your Trezor passphrase")) - self.passphrase = unicodedata.normalize('NFKD', unicode(passphrase)) if passphrase else '' - else: - assert type(self.win) is InstallWizard - from electrum_gui.qt.password_dialog import PasswordDialog - d = PasswordDialog(self.win, None, None, self.message, False) - confirmed, p, passphrase = d.run() - if not confirmed: - self.win.show_critical(_("Password request canceled")) - self.passphrase = None - else: - self.passphrase = unicodedata.normalize('NFKD', unicode(passphrase)) if passphrase else '' - self.done.set() - - def message_dialog(self): - # Called more than once during signing, to confirm output and fee - self.dialog_stop() - self.d = WindowModalDialog(self.win, _('Please Check Trezor Device')) - l = QLabel(self.message) - vbox = QVBoxLayout(self.d) - vbox.addWidget(l) - self.d.show() - - def dialog_stop(self): - if self.d: - self.d.hide() - self.d = None +class TrezorQtHandler(QtHandler): + device = 'Trezor' + pin_matrix_widget_class = PinMatrixWidget class Plugin(TrezorPlugin): DIR diff --git a/plugins/trezor/qt_generic.py b/plugins/trezor/qt_generic.py t@@ -0,0 +1,91 @@ +from unicodedata import normalize +import threading + +from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL +import PyQt4.QtCore as QtCore +from electrum_gui.qt.main_window import ElectrumWindow +from electrum_gui.qt.installwizard import InstallWizard +from electrum_gui.qt.password_dialog import PasswordDialog +from electrum_gui.qt.util import * + +from electrum.i18n import _ + +class QtHandler: + '''An interface between the GUI (here, QT) and the device handling + logic for handling I/O. This is a generic implementation of the + Trezor protocol; derived classes can customize it.''' + + # Derived classes must provide: + # device a string, e.g. "Trezor" + # pin_matrix_widget_class + + def __init__(self, win): + win.connect(win, SIGNAL('message_done'), self.dialog_stop) + win.connect(win, SIGNAL('message_dialog'), self.message_dialog) + win.connect(win, SIGNAL('pin_dialog'), self.pin_dialog) + win.connect(win, SIGNAL('passphrase_dialog'), self.passphrase_dialog) + self.win = win + self.done = threading.Event() + self.dialog = None + + def stop(self): + self.win.emit(SIGNAL('message_done')) + + def show_message(self, msg): + self.win.emit(SIGNAL('message_dialog'), msg) + + def get_pin(self, msg): + self.done.clear() + self.win.emit(SIGNAL('pin_dialog'), msg) + self.done.wait() + return self.response + + def get_passphrase(self, msg): + self.done.clear() + self.win.emit(SIGNAL('passphrase_dialog'), msg) + self.done.wait() + return self.passphrase + + def pin_dialog(self, msg): + d = WindowModalDialog(self.win, _("Enter PIN")) + matrix = self.pin_matrix_widget_class() + vbox = QVBoxLayout() + vbox.addWidget(QLabel(msg)) + vbox.addWidget(matrix) + vbox.addLayout(Buttons(CancelButton(d), OkButton(d))) + d.setLayout(vbox) + if not d.exec_(): + self.response = None # FIXME: this is lost? + self.response = str(matrix.get_value()) + self.done.set() + + def passphrase_dialog(self, msg): + if type(self.win) is ElectrumWindow: + msg = _("Please enter your %s passphrase") % self.device + passphrase = self.win.password_dialog(msg) + else: + assert type(self.win) is InstallWizard + d = PasswordDialog(self.win, None, None, msg, False) + confirmed, p, passphrase = d.run() + + if passphrase is None: + self.win.show_critical(_("Passphrase request canceled")) + else: + passphrase = normalize('NFKD', unicode(passphrase)) + self.passphrase = passphrase + self.done.set() + + def message_dialog(self, msg): + # Called more than once during signing, to confirm output and fee + self.dialog_stop() + msg = _('Please check your %s Device') % self.device + self.dialog = WindowModalDialog(self.win, msg) + l = QLabel(msg) + vbox = QVBoxLayout(self.dialog) + vbox.addWidget(l) + self.dialog.show() + + def dialog_stop(self): + if self.dialog: + self.dialog.hide() + self.dialog = None