diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py index 49674f8d..104e7f44 100644 --- a/gui/qt/installwizard.py +++ b/gui/qt/installwizard.py @@ -407,11 +407,11 @@ class InstallWizard(WindowModalDialog, MessageBoxMixin): return self.exec_() def password_dialog(self): - msg = _("Please choose a password to encrypt your wallet keys.")+'\n'\ - +_("Leave these fields empty if you want to disable encryption.") - from password_dialog import make_password_dialog, run_password_dialog - self.set_layout( make_password_dialog(self, None, msg) ) - return run_password_dialog(self, None, self)[2] + from password_dialog import PasswordDialog + msg = _("Please choose a password to encrypt your wallet keys.\n" + "Leave these fields empty if you want to disable encryption.") + dialog = PasswordDialog(self, None, _("Choose a password"), msg, True) + return dialog.run()[2] def run(self, action): if self.storage.file_exists and action != 'new': diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py index a65fa358..c329ad93 100644 --- a/gui/qt/main_window.py +++ b/gui/qt/main_window.py @@ -1852,8 +1852,39 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError): def change_password_dialog(self): from password_dialog import PasswordDialog - d = PasswordDialog(self.wallet, self) - d.run() + + if self.wallet and self.wallet.is_watching_only(): + self.show_error(_('This is a watching-only wallet')) + return + + msg = (_('Your wallet is encrypted. Use this dialog to change your ' + 'password. To disable wallet encryption, enter an empty new ' + 'password.') if self.wallet.use_encryption + else _('Your wallet keys are not encrypted')) + d = PasswordDialog(self, self.wallet, _("Set Password"), msg, True) + ok, password, new_password = d.run() + if not ok: + return + + try: + self.wallet.check_password(password) + except BaseException as e: + self.show_error(str(e)) + return + + try: + self.wallet.update_password(password, new_password) + except: + traceback.print_exc(file=sys.stdout) + self.show_error(_('Failed to update password')) + return + + if new_password: + msg = _('Password was updated successfully') + else: + msg = _('This wallet is not encrypted') + self.show_message(msg, title=_("Success")) + self.update_lock_icon() def toggle_search(self): diff --git a/gui/qt/password_dialog.py b/gui/qt/password_dialog.py index 104cc94d..6f0b975b 100644 --- a/gui/qt/password_dialog.py +++ b/gui/qt/password_dialog.py @@ -23,84 +23,6 @@ from util import * import re import math - - -def make_password_dialog(self, wallet, msg, new_pass=True): - - self.pw = QLineEdit() - self.pw.setEchoMode(2) - self.new_pw = QLineEdit() - self.new_pw.setEchoMode(2) - self.conf_pw = QLineEdit() - self.conf_pw.setEchoMode(2) - - vbox = QVBoxLayout() - label = QLabel(msg) - label.setWordWrap(True) - - grid = QGridLayout() - grid.setSpacing(8) - grid.setColumnMinimumWidth(0, 70) - grid.setColumnStretch(1,1) - - logo = QLabel() - lockfile = ":icons/lock.png" if wallet and wallet.use_encryption else ":icons/unlock.png" - logo.setPixmap(QPixmap(lockfile).scaledToWidth(36)) - logo.setAlignment(Qt.AlignCenter) - - grid.addWidget(logo, 0, 0) - grid.addWidget(label, 0, 1, 1, 2) - vbox.addLayout(grid) - - grid = QGridLayout() - grid.setSpacing(8) - grid.setColumnMinimumWidth(0, 250) - grid.setColumnStretch(1,1) - - if wallet and wallet.use_encryption: - grid.addWidget(QLabel(_('Password')), 0, 0) - grid.addWidget(self.pw, 0, 1) - - grid.addWidget(QLabel(_('New Password') if new_pass else _('Password')), 1, 0) - grid.addWidget(self.new_pw, 1, 1) - - grid.addWidget(QLabel(_('Confirm Password')), 2, 0) - grid.addWidget(self.conf_pw, 2, 1) - vbox.addLayout(grid) - - #Password Strength Label - self.pw_strength = QLabel() - grid.addWidget(self.pw_strength, 3, 0, 1, 2) - self.new_pw.textChanged.connect(lambda: update_password_strength(self.pw_strength, self.new_pw.text())) - - vbox.addStretch(1) - vbox.addLayout(Buttons(CancelButton(self), OkButton(self))) - return vbox - - -def run_password_dialog(self, wallet, parent): - - if wallet and wallet.is_watching_only(): - QMessageBox.information(parent, _('Error'), _('This is a watching-only wallet'), _('OK')) - return False, None, None - - if not self.exec_(): - return False, None, None - - password = unicode(self.pw.text()) if wallet and wallet.use_encryption else None - new_password = unicode(self.new_pw.text()) - new_password2 = unicode(self.conf_pw.text()) - - if new_password != new_password2: - QMessageBox.warning(parent, _('Error'), _('Passwords do not match'), _('OK')) - # Retry - return run_password_dialog(self, wallet, parent) - - if not new_password: - new_password = None - - return True, password, new_password - def check_password_strength(password): ''' @@ -117,57 +39,89 @@ def check_password_strength(password): password_strength = {0:"Weak",1:"Medium",2:"Strong",3:"Very Strong"} return password_strength[min(3, int(score))] - -def update_password_strength(pw_strength_label,password): - - ''' - call the function check_password_strength and update the label pw_strength interactively as the user is typing the password - :param pw_strength_label: the label pw_strength - :param password: password entered in New Password text box - :return: None - ''' - if password: - colors = {"Weak":"Red","Medium":"Blue","Strong":"Green", "Very Strong":"Green"} - strength = check_password_strength(password) - label = _("Password Strength")+ ": "+"" + strength + "" - else: - label = "" - pw_strength_label.setText(label) - - - class PasswordDialog(WindowModalDialog): - def __init__(self, wallet, parent): - WindowModalDialog.__init__(self, parent,_("Set Password")) + def __init__(self, parent, wallet, title, msg, new_pass): + WindowModalDialog.__init__(self, parent, title) self.wallet = wallet - self.parent = parent - msg = (_('Your wallet is encrypted. Use this dialog to change your password.') + ' '\ - +_('To disable wallet encryption, enter an empty new password.')) \ - if wallet.use_encryption else _('Your wallet keys are not encrypted') - self.setLayout(make_password_dialog(self, wallet, msg)) + self.pw = QLineEdit() + self.pw.setEchoMode(2) + self.new_pw = QLineEdit() + self.new_pw.setEchoMode(2) + self.conf_pw = QLineEdit() + self.conf_pw.setEchoMode(2) + + vbox = QVBoxLayout() + label = QLabel(msg) + label.setWordWrap(True) + + grid = QGridLayout() + grid.setSpacing(8) + grid.setColumnMinimumWidth(0, 70) + grid.setColumnStretch(1,1) + + logo = QLabel() + logo.setAlignment(Qt.AlignCenter) + + grid.addWidget(logo, 0, 0) + grid.addWidget(label, 0, 1, 1, 2) + vbox.addLayout(grid) + + grid = QGridLayout() + grid.setSpacing(8) + grid.setColumnMinimumWidth(0, 250) + grid.setColumnStretch(1,1) + + if wallet and wallet.use_encryption: + grid.addWidget(QLabel(_('Password')), 0, 0) + grid.addWidget(self.pw, 0, 1) + lockfile = ":icons/lock.png" + else: + self.pw = None + lockfile = ":icons/unlock.png" + logo.setPixmap(QPixmap(lockfile).scaledToWidth(36)) + + grid.addWidget(QLabel(_('New Password') if new_pass else _('Password')), 1, 0) + grid.addWidget(self.new_pw, 1, 1) + + grid.addWidget(QLabel(_('Confirm Password')), 2, 0) + grid.addWidget(self.conf_pw, 2, 1) + vbox.addLayout(grid) + + # Password Strength Label + self.pw_strength = QLabel() + grid.addWidget(self.pw_strength, 3, 0, 1, 2) + self.new_pw.textChanged.connect(self.pw_changed) + self.conf_pw.textChanged.connect(self.check_OKButton) + + self.OKButton = OkButton(self) + vbox.addStretch(1) + vbox.addLayout(Buttons(CancelButton(self), self.OKButton)) + self.setLayout(vbox) + + def pw_changed(self): + password = self.new_pw.text() + if password: + colors = {"Weak":"Red", "Medium":"Blue", "Strong":"Green", + "Very Strong":"Green"} + strength = check_password_strength(password) + label = (_("Password Strength") + ": " + "" + strength + "") + else: + label = "" + self.pw_strength.setText(label) + self.check_OKButton() + + def check_OKButton(self): + self.OKButton.setEnabled(self.new_pw.text() == self.conf_pw.text()) def run(self): - ok, password, new_password = run_password_dialog(self, self.wallet, self.parent) - if not ok: - return - - try: - self.wallet.check_password(password) - except BaseException as e: - QMessageBox.warning(self.parent, _('Error'), str(e), _('OK')) + if not self.exec_(): return False, None, None - try: - self.wallet.update_password(password, new_password) - except: - import traceback, sys - traceback.print_exc(file=sys.stdout) - QMessageBox.warning(self.parent, _('Error'), _('Failed to update password'), _('OK')) - return + password = unicode(self.pw.text()) if self.pw else None + new_password = unicode(self.new_pw.text()) + new_password2 = unicode(self.conf_pw.text()) - if new_password: - QMessageBox.information(self.parent, _('Success'), _('Password was updated successfully'), _('OK')) - else: - QMessageBox.information(self.parent, _('Success'), _('This wallet is not encrypted'), _('OK')) + return True, password or None, new_password or None diff --git a/plugins/keepkey/qt.py b/plugins/keepkey/qt.py index ab6ce807..db842b57 100644 --- a/plugins/keepkey/qt.py +++ b/plugins/keepkey/qt.py @@ -1,4 +1,4 @@ -from PyQt4.Qt import QMessageBox, QDialog, QVBoxLayout, QLabel, QThread, SIGNAL, QGridLayout, QInputDialog, QPushButton +from PyQt4.Qt import QMessageBox, QVBoxLayout, QLabel, QThread, SIGNAL, QGridLayout, QInputDialog, QPushButton import PyQt4.QtCore as QtCore from electrum_gui.qt.util import * from electrum_gui.qt.main_window import StatusBarButton, ElectrumWindow @@ -73,7 +73,7 @@ class Plugin(KeepKeyPlugin): return get_label = lambda: self.get_client().features.label update_label = lambda: current_label_label.setText("Label: %s" % get_label()) - d = QDialog() + d = WindowModalDialog(window, _("KeepKey Settings")) layout = QGridLayout(d) layout.addWidget(QLabel("KeepKey Options"),0,0) layout.addWidget(QLabel("ID:"),1,0) @@ -132,10 +132,7 @@ class KeepKeyQtHandler: return self.passphrase def pin_dialog(self): - d = QDialog(None) - d.setModal(1) - d.setWindowTitle(_("Enter PIN")) - d.setWindowFlags(d.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) + d = WindowModalDialog(self.win, _("Enter PIN")) matrix = PinMatrixWidget() vbox = QVBoxLayout() vbox.addWidget(QLabel(self.message)) @@ -153,23 +150,18 @@ class KeepKeyQtHandler: self.passphrase = unicodedata.normalize('NFKD', unicode(passphrase)) if passphrase else '' else: assert type(self.win) is InstallWizard - from electrum_gui.qt.password_dialog import make_password_dialog, run_password_dialog - d = QDialog() - d.setModal(1) - d.setLayout(make_password_dialog(d, None, self.message, False)) - confirmed, p, passphrase = run_password_dialog(d, None, None) + 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: - QMessageBox.critical(None, _('Error'), _("Password request canceled"), _('OK')) + 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): - self.d = QDialog() - self.d.setModal(1) - self.d.setWindowTitle('Please Check KeepKey Device') - self.d.setWindowFlags(self.d.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) + self.d = WindowModalDialog(self.win, _('Please Check KeepKey Device')) l = QLabel(self.message) vbox = QVBoxLayout(self.d) vbox.addWidget(l) @@ -182,5 +174,3 @@ class KeepKeyQtHandler: def dialog_stop(self): self.d.hide() - - diff --git a/plugins/trezor/qt.py b/plugins/trezor/qt.py index 0926b331..eb11f062 100644 --- a/plugins/trezor/qt.py +++ b/plugins/trezor/qt.py @@ -1,4 +1,4 @@ -from PyQt4.Qt import QMessageBox, QDialog, QVBoxLayout, QLabel, QThread, SIGNAL, QGridLayout, QInputDialog, QPushButton +from PyQt4.Qt import QMessageBox, QVBoxLayout, QLabel, QThread, SIGNAL, QGridLayout, QInputDialog, QPushButton import PyQt4.QtCore as QtCore from electrum_gui.qt.util import * from electrum_gui.qt.main_window import StatusBarButton, ElectrumWindow @@ -46,10 +46,7 @@ class TrezorQtHandler: return self.passphrase def pin_dialog(self): - d = QDialog(None) - d.setModal(1) - d.setWindowTitle(_("Enter PIN")) - d.setWindowFlags(d.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) + d = WindowModalDialog(self.win, _("Enter PIN")) matrix = PinMatrixWidget() vbox = QVBoxLayout() vbox.addWidget(QLabel(self.message)) @@ -67,23 +64,18 @@ class TrezorQtHandler: self.passphrase = unicodedata.normalize('NFKD', unicode(passphrase)) if passphrase else '' else: assert type(self.win) is InstallWizard - from electrum_gui.qt.password_dialog import make_password_dialog, run_password_dialog - d = QDialog() - d.setModal(1) - d.setLayout(make_password_dialog(d, None, self.message, False)) - confirmed, p, passphrase = run_password_dialog(d, None, None) + 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: - QMessageBox.critical(None, _('Error'), _("Password request canceled"), _('OK')) + 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): - self.d = QDialog() - self.d.setModal(1) - self.d.setWindowTitle('Please Check Trezor Device') - self.d.setWindowFlags(self.d.windowFlags() | QtCore.Qt.WindowStaysOnTopHint) + self.d = WindowModalDialog(self.win, _('Please Check Trezor Device')) l = QLabel(self.message) vbox = QVBoxLayout(self.d) vbox.addWidget(l) @@ -171,7 +163,7 @@ class Plugin(TrezorPlugin): return get_label = lambda: self.get_client().features.label update_label = lambda: current_label_label.setText("Label: %s" % get_label()) - d = QDialog() + d = WindowModalDialog(window, _("Trezor Settings")) layout = QGridLayout(d) layout.addWidget(QLabel("Trezor Options"),0,0) layout.addWidget(QLabel("ID:"),1,0)