commit 134ae3d0440a60bf3912c1ff58b8e53d039b0157
parent e461c1c818e5ffff7a510d372661a0e7eb3482c3
Author: Neil Booth <kyuupichan@gmail.com>
Date: Sat, 30 Jan 2016 12:46:54 +0900
hw_wallet: separate out common QtHandler code
Diffstat:
3 files changed, 135 insertions(+), 99 deletions(-)
diff --git a/plugins/hw_wallet/__init__.py b/plugins/hw_wallet/__init__.py
@@ -1 +1,2 @@
from hw_wallet import BIP44_HW_Wallet
+from qt import QtHandlerBase
diff --git a/plugins/hw_wallet/qt.py b/plugins/hw_wallet/qt.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python2
+# -*- mode: python -*-
+#
+# Electrum - lightweight Bitcoin client
+# Copyright (C) 2016 The Electrum developers
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import threading
+
+from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL
+from electrum_gui.qt.password_dialog import PasswordDialog, PW_PASSPHRASE
+from electrum_gui.qt.util import *
+
+from electrum.i18n import _
+from electrum.util import PrintError
+from electrum.wallet import BIP44_Wallet
+
+# The trickiest thing about this handler was getting windows properly
+# parented on MacOSX.
+class QtHandlerBase(QObject, PrintError):
+ '''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.'''
+
+ qcSig = pyqtSignal(object, object)
+
+ def __init__(self, win, device):
+ super(QtHandlerBase, self).__init__()
+ win.connect(win, SIGNAL('clear_dialog'), self.clear_dialog)
+ win.connect(win, SIGNAL('error_dialog'), self.error_dialog)
+ win.connect(win, SIGNAL('message_dialog'), self.message_dialog)
+ win.connect(win, SIGNAL('passphrase_dialog'), self.passphrase_dialog)
+ win.connect(win, SIGNAL('word_dialog'), self.word_dialog)
+ self.qcSig.connect(self.win_query_choice)
+ self.win = win
+ self.device = device
+ self.dialog = None
+ self.done = threading.Event()
+
+ def top_level_window(self):
+ return self.win.top_level_window()
+
+ def watching_only_changed(self):
+ self.win.emit(SIGNAL('watching_only_changed'))
+
+ def query_choice(self, msg, labels):
+ self.done.clear()
+ self.qcSig.emit(msg, labels)
+ self.done.wait()
+ return self.choice
+
+ def show_message(self, msg, on_cancel=None):
+ self.win.emit(SIGNAL('message_dialog'), msg, on_cancel)
+
+ def show_error(self, msg):
+ self.win.emit(SIGNAL('error_dialog'), msg)
+
+ def finished(self):
+ self.win.emit(SIGNAL('clear_dialog'))
+
+ def get_word(self, msg):
+ self.done.clear()
+ self.win.emit(SIGNAL('word_dialog'), msg)
+ self.done.wait()
+ return self.word
+
+ def get_passphrase(self, msg):
+ self.done.clear()
+ self.win.emit(SIGNAL('passphrase_dialog'), msg)
+ self.done.wait()
+ return self.passphrase
+
+ def passphrase_dialog(self, msg):
+ d = PasswordDialog(self.top_level_window(), None, msg, PW_PASSPHRASE)
+ confirmed, p, passphrase = d.run()
+ if confirmed:
+ passphrase = BIP44_Wallet.normalize_passphrase(passphrase)
+ self.passphrase = passphrase
+ self.done.set()
+
+ def word_dialog(self, msg):
+ dialog = WindowModalDialog(self.top_level_window(), "")
+ hbox = QHBoxLayout(dialog)
+ hbox.addWidget(QLabel(msg))
+ text = QLineEdit()
+ text.setMaximumWidth(100)
+ text.returnPressed.connect(dialog.accept)
+ hbox.addWidget(text)
+ hbox.addStretch(1)
+ dialog.exec_() # Firmware cannot handle cancellation
+ self.word = unicode(text.text())
+ self.done.set()
+
+ def message_dialog(self, msg, on_cancel):
+ # Called more than once during signing, to confirm output and fee
+ self.clear_dialog()
+ title = _('Please check your %s device') % self.device
+ self.dialog = dialog = WindowModalDialog(self.top_level_window(), title)
+ l = QLabel(msg)
+ vbox = QVBoxLayout(dialog)
+ vbox.addWidget(l)
+ if on_cancel:
+ dialog.rejected.connect(on_cancel)
+ vbox.addLayout(Buttons(CancelButton(dialog)))
+ dialog.show()
+
+ def error_dialog(self, msg):
+ self.win.show_error(msg, parent=self.top_level_window())
+
+ def clear_dialog(self):
+ if self.dialog:
+ self.dialog.accept()
+ self.dialog = None
+
+ def win_query_choice(self, msg, labels):
+ self.choice = self.win.query_choice(msg, labels)
+ self.done.set()
diff --git a/plugins/trezor/qt_generic.py b/plugins/trezor/qt_generic.py
@@ -5,9 +5,9 @@ from PyQt4.Qt import Qt
from PyQt4.Qt import QGridLayout, QInputDialog, QPushButton
from PyQt4.Qt import QVBoxLayout, QLabel, SIGNAL
from electrum_gui.qt.main_window import StatusBarButton
-from electrum_gui.qt.password_dialog import PasswordDialog, PW_PASSPHRASE
from electrum_gui.qt.util import *
-from .plugin import TrezorCompatiblePlugin, TIM_NEW, TIM_RECOVER, TIM_MNEMONIC
+from .plugin import TIM_NEW, TIM_RECOVER, TIM_MNEMONIC
+from ..hw_wallet import QtHandlerBase
from electrum.i18n import _
from electrum.plugins import hook, DeviceMgr
@@ -126,54 +126,18 @@ class CharacterDialog(WindowModalDialog):
if self.loop.exec_():
self.data = None # User cancelled
-# By far the trickiest thing about this handler is the window stack;
-# MacOSX is very fussy the modal dialogs are perfectly parented
-class QtHandler(QObject, PrintError):
- '''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.'''
+
+class QtHandler(QtHandlerBase):
charSig = pyqtSignal(object)
- qcSig = pyqtSignal(object, object)
def __init__(self, win, pin_matrix_widget_class, device):
- super(QtHandler, self).__init__()
- win.connect(win, SIGNAL('clear_dialog'), self.clear_dialog)
- win.connect(win, SIGNAL('error_dialog'), self.error_dialog)
- win.connect(win, SIGNAL('message_dialog'), self.message_dialog)
+ super(QtHandler, self).__init__(win, device)
win.connect(win, SIGNAL('pin_dialog'), self.pin_dialog)
- win.connect(win, SIGNAL('passphrase_dialog'), self.passphrase_dialog)
- win.connect(win, SIGNAL('word_dialog'), self.word_dialog)
self.charSig.connect(self.update_character_dialog)
- self.qcSig.connect(self.win_query_choice)
- self.win = win
self.pin_matrix_widget_class = pin_matrix_widget_class
- self.device = device
- self.dialog = None
- self.done = threading.Event()
self.character_dialog = None
- def top_level_window(self):
- return self.win.top_level_window()
-
- def watching_only_changed(self):
- self.win.emit(SIGNAL('watching_only_changed'))
-
- def query_choice(self, msg, labels):
- self.done.clear()
- self.qcSig.emit(msg, labels)
- self.done.wait()
- return self.choice
-
- def show_message(self, msg, on_cancel=None):
- self.win.emit(SIGNAL('message_dialog'), msg, on_cancel)
-
- def show_error(self, msg):
- self.win.emit(SIGNAL('error_dialog'), msg)
-
- def finished(self):
- self.win.emit(SIGNAL('clear_dialog'))
-
def get_char(self, msg):
self.done.clear()
self.charSig.emit(msg)
@@ -190,18 +154,6 @@ class QtHandler(QObject, PrintError):
self.done.wait()
return self.response
- def get_word(self, msg):
- self.done.clear()
- self.win.emit(SIGNAL('word_dialog'), msg)
- self.done.wait()
- return self.word
-
- 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):
# Needed e.g. when resetting a device
self.clear_dialog()
@@ -216,58 +168,12 @@ class QtHandler(QObject, PrintError):
self.response = str(matrix.get_value())
self.done.set()
- def passphrase_dialog(self, msg):
- d = PasswordDialog(self.top_level_window(), None, msg, PW_PASSPHRASE)
- confirmed, p, passphrase = d.run()
- if confirmed:
- passphrase = BIP44_Wallet.normalize_passphrase(passphrase)
- self.passphrase = passphrase
- self.done.set()
-
- def word_dialog(self, msg):
- dialog = WindowModalDialog(self.top_level_window(), "")
- hbox = QHBoxLayout(dialog)
- hbox.addWidget(QLabel(msg))
- text = QLineEdit()
- text.setMaximumWidth(100)
- text.returnPressed.connect(dialog.accept)
- hbox.addWidget(text)
- hbox.addStretch(1)
- dialog.exec_() # Firmware cannot handle cancellation
- self.word = unicode(text.text())
- self.done.set()
-
def update_character_dialog(self, msg):
if not self.character_dialog:
self.character_dialog = CharacterDialog(self.top_level_window())
self.character_dialog.get_char(msg.word_pos, msg.character_pos)
self.done.set()
- def message_dialog(self, msg, on_cancel):
- # Called more than once during signing, to confirm output and fee
- self.clear_dialog()
- title = _('Please check your %s device') % self.device
- self.dialog = dialog = WindowModalDialog(self.top_level_window(), title)
- l = QLabel(msg)
- vbox = QVBoxLayout(dialog)
- vbox.addWidget(l)
- if on_cancel:
- dialog.rejected.connect(on_cancel)
- vbox.addLayout(Buttons(CancelButton(dialog)))
- dialog.show()
-
- def error_dialog(self, msg):
- self.win.show_error(msg, parent=self.top_level_window())
-
- def clear_dialog(self):
- if self.dialog:
- self.dialog.accept()
- self.dialog = None
-
- def win_query_choice(self, msg, labels):
- self.choice = self.win.query_choice(msg, labels)
- self.done.set()
-
def request_trezor_init_settings(self, method, device):
wizard = self.win