URI: 
       tMerge branch 'master' of git://github.com/spesmilo/electrum - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 8bcd13242309d5888c92c7a03db60a42f6573446
   DIR parent acbe67fd1f4d3bd0755707ee90b97295b5d7ff99
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Wed, 23 Dec 2015 10:54:45 +0100
       
       Merge branch 'master' of git://github.com/spesmilo/electrum
       
       Diffstat:
         M gui/qt/installwizard.py             |      10 +++++-----
         M gui/qt/main_window.py               |      62 ++++++++++++++++++++++++-------
         M gui/qt/password_dialog.py           |     200 ++++++++++++-------------------
         M gui/qt/paytoedit.py                 |       8 --------
         M gui/qt/qrcodewidget.py              |      16 +++++++---------
         M gui/qt/qrtextedit.py                |       8 ++++----
         M gui/qt/transaction_dialog.py        |      16 ++++------------
         M gui/qt/util.py                      |      22 +++++++++++++++++-----
         M lib/qrscanner.py                    |       2 +-
         M plugins/keepkey/qt.py               |      26 ++++++++------------------
         M plugins/trezor/qt.py                |      24 ++++++++----------------
       
       11 files changed, 179 insertions(+), 215 deletions(-)
       ---
   DIR diff --git a/gui/qt/installwizard.py b/gui/qt/installwizard.py
       t@@ -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':
   DIR diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
       t@@ -48,7 +48,7 @@ from electrum import Imported_Wallet, paymentrequest
        from amountedit import BTCAmountEdit, MyLineEdit, BTCkBEdit
        from network_dialog import NetworkDialog
        from qrcodewidget import QRCodeWidget, QRDialog
       -from qrtextedit import ScanQRTextEdit, ShowQRTextEdit
       +from qrtextedit import ShowQRTextEdit
        from transaction_dialog import show_transaction
        from installwizard import InstallWizard
        
       t@@ -1568,6 +1568,13 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
            def paytomany(self):
                self.tabs.setCurrentIndex(1)
                self.payto_e.paytomany()
       +        msg = '\n'.join([
       +            _('Enter a list of outputs in the \'Pay to\' field.'),
       +            _('One output per line.'),
       +            _('Format: address, amount'),
       +            _('You may load a CSV file using the file icon.')
       +        ])
       +        self.show_warning(msg, title=_('Pay to many'))
        
            def payto_contacts(self, labels):
                paytos = [self.get_contact_payto(label) for label in labels]
       t@@ -1852,8 +1859,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):
       t@@ -1985,10 +2023,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
        
        
        
       -    def show_qrcode(self, data, title = _("QR code")):
       +    def show_qrcode(self, data, title = _("QR code"), parent=None):
                if not data:
                    return
       -        d = QRDialog(data, self, title)
       +        d = QRDialog(data, parent or self, title)
                d.exec_()
        
            def show_public_keys(self, address):
       t@@ -2154,10 +2192,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                layout.addLayout(hbox, 4, 1)
                d.exec_()
        
       -
       -    def question(self, msg):
       -        return QMessageBox.question(self, _('Message'), msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes
       -
            def password_dialog(self, msg=None, parent=None):
                if parent == None:
                    parent = self
       t@@ -2205,7 +2239,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
                from electrum import qrscanner
                try:
                    data = qrscanner.scan_qr(self.config)
       -        except BaseException as e:
       +        except e:
                    self.show_error(str(e))
                    return
                if not data:
       t@@ -2495,10 +2529,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
            @protected
            def do_import_privkey(self, password):
                if not self.wallet.has_imported_keys():
       -            r = QMessageBox.question(None, _('Warning'), '<b>'+_('Warning') +':\n</b><br/>'+ _('Imported keys are not recoverable from seed.') + ' ' \
       -                                         + _('If you ever need to restore your wallet from its seed, these keys will be lost.') + '<p>' \
       -                                         + _('Are you sure you understand what you are doing?'), 3, 4)
       -            if r == 4: return
       +            if not self.question('<b>'+_('Warning') +':\n</b><br/>'+ _('Imported keys are not recoverable from seed.') + ' ' \
       +                                 + _('If you ever need to restore your wallet from its seed, these keys will be lost.') + '<p>' \
       +                                 + _('Are you sure you understand what you are doing?'), title=_('Warning')):
       +                return
        
                text = text_dialog(self, _('Import private keys'), _("Enter private keys")+':', _("Import"))
                if not text: return
   DIR diff --git a/gui/qt/password_dialog.py b/gui/qt/password_dialog.py
       t@@ -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):
        
            '''
       t@@ -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")+ ": "+"<font color=" + colors[strength] + ">" + strength + "</font>"
       -    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") + ": " + "<font color="
       +                     + colors[strength] + ">" + strength + "</font>")
       +        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
   DIR diff --git a/gui/qt/paytoedit.py b/gui/qt/paytoedit.py
       t@@ -160,16 +160,8 @@ class PayToEdit(ScanQRTextEdit):
                return len(self.lines()) > 1
        
            def paytomany(self):
       -        from electrum.i18n import _
                self.setText("\n\n\n")
                self.update_size()
       -        msg = '\n'.join([
       -            _('Enter a list of outputs in the \'Pay to\' field.'),
       -            _('One output per line.'),
       -            _('Format: address, amount.'),
       -            _('You may load a CSV file using the file icon.')
       -        ])
       -        QMessageBox.warning(self, _('Pay to many'), msg, _('OK'))
        
            def update_size(self):
                docHeight = self.document().size().height()
   DIR diff --git a/gui/qt/qrcodewidget.py b/gui/qt/qrcodewidget.py
       t@@ -1,6 +1,5 @@
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
       -import PyQt4.QtCore as QtCore
        import PyQt4.QtGui as QtGui
        
        import os
       t@@ -9,6 +8,7 @@ import qrcode
        import electrum
        from electrum import bmp
        from electrum.i18n import _
       +from util import WindowModalDialog, MessageBoxMixin
        
        
        class QRCodeWidget(QWidget):
       t@@ -83,13 +83,11 @@ class QRCodeWidget(QWidget):
        
        
        
       -class QRDialog(QDialog):
       +class QRDialog(WindowModalDialog, MessageBoxMixin):
        
            def __init__(self, data, parent=None, title = "", show_text=False):
       -        QDialog.__init__(self, parent)
       +        WindowModalDialog.__init__(self, parent, title)
        
       -        d = self
       -        d.setWindowTitle(title)
                vbox = QVBoxLayout()
                qrw = QRCodeWidget(data)
                vbox.addWidget(qrw, 1)
       t@@ -107,12 +105,12 @@ class QRDialog(QDialog):
        
                    def print_qr():
                        bmp.save_qrcode(qrw.qr, filename)
       -                QMessageBox.information(None, _('Message'), _("QR code saved to file") + " " + filename, _('OK'))
       +                self.show_message(_("QR code saved to file") + " " + filename)
        
                    def copy_to_clipboard():
                        bmp.save_qrcode(qrw.qr, filename)
                        QApplication.clipboard().setImage(QImage(filename))
       -                QMessageBox.information(None, _('Message'), _("QR code saved to clipboard"), _('OK'))
       +                self.show_message(_("QR code copied to clipboard"))
        
                    b = QPushButton(_("Copy"))
                    hbox.addWidget(b)
       t@@ -124,8 +122,8 @@ class QRDialog(QDialog):
        
                b = QPushButton(_("Close"))
                hbox.addWidget(b)
       -        b.clicked.connect(d.accept)
       +        b.clicked.connect(self.accept)
                b.setDefault(True)
        
                vbox.addLayout(hbox)
       -        d.setLayout(vbox)
       +        self.setLayout(vbox)
   DIR diff --git a/gui/qt/qrtextedit.py b/gui/qt/qrtextedit.py
       t@@ -3,7 +3,7 @@ from electrum.plugins import run_hook
        from PyQt4.QtGui import *
        from PyQt4.QtCore import *
        
       -from util import ButtonsTextEdit
       +from util import ButtonsTextEdit, MessageBoxMixin
        
        
        class ShowQRTextEdit(ButtonsTextEdit):
       t@@ -29,7 +29,7 @@ class ShowQRTextEdit(ButtonsTextEdit):
                m.exec_(e.globalPos())
        
        
       -class ScanQRTextEdit(ButtonsTextEdit):
       +class ScanQRTextEdit(ButtonsTextEdit, MessageBoxMixin):
        
            def __init__(self, text=""):
                ButtonsTextEdit.__init__(self, text)
       t@@ -50,8 +50,8 @@ class ScanQRTextEdit(ButtonsTextEdit):
                from electrum import qrscanner, get_config
                try:
                    data = qrscanner.scan_qr(get_config())
       -        except BaseException, e:
       -            QMessageBox.warning(self, _('Error'), _(e), _('OK'))
       +        except BaseException as e:
       +            self.show_error(str(e))
                    return ""
                if type(data) != str:
                    return
   DIR diff --git a/gui/qt/transaction_dialog.py b/gui/qt/transaction_dialog.py
       t@@ -38,7 +38,7 @@ def show_transaction(tx, parent, desc=None, prompt_if_unsaved=False):
            dialogs.append(d)
            d.show()
        
       -class TxDialog(QDialog):
       +class TxDialog(QDialog, MessageBoxMixin):
        
            def __init__(self, tx, parent, desc, prompt_if_unsaved):
                '''Transactions in the wallet will show their description.
       t@@ -62,7 +62,7 @@ class TxDialog(QDialog):
        
                vbox.addWidget(QLabel(_("Transaction ID:")))
                self.tx_hash_e  = ButtonsLineEdit()
       -        qr_show = lambda: self.parent.show_qrcode(str(self.tx_hash_e.text()), 'Transaction ID')
       +        qr_show = lambda: self.parent.show_qrcode(str(self.tx_hash_e.text()), 'Transaction ID', parent=self)
                self.tx_hash_e.addButton(":icons/qrcode.png", qr_show, _("Show as QR code"))
                self.tx_hash_e.setReadOnly(True)
                vbox.addWidget(self.tx_hash_e)
       t@@ -122,10 +122,7 @@ class TxDialog(QDialog):
        
            def closeEvent(self, event):
                if (self.prompt_if_unsaved and not self.saved and not self.broadcast
       -            and QMessageBox.question(
       -                self, _('Warning'),
       -                _('This transaction is not saved. Close anyway?'),
       -                QMessageBox.Yes | QMessageBox.No) == QMessageBox.No):
       +            and not self.question(_('This transaction is not saved. Close anyway?'), title=_("Warning"))):
                    event.ignore()
                else:
                    event.accept()
       t@@ -135,7 +132,7 @@ class TxDialog(QDialog):
                text = self.tx.raw.decode('hex')
                text = base_encode(text, base=43)
                try:
       -            self.parent.show_qrcode(text, 'Transaction')
       +            self.parent.show_qrcode(text, 'Transaction', parent=self)
                except Exception as e:
                    self.show_message(str(e))
        
       t@@ -291,8 +288,3 @@ class TxDialog(QDialog):
                        cursor.insertText(format_amount(v), ext)
                    cursor.insertBlock()
                vbox.addWidget(o_text)
       -
       -
       -
       -    def show_message(self, msg):
       -        QMessageBox.information(self, _('Message'), msg, _('OK'))
   DIR diff --git a/gui/qt/util.py b/gui/qt/util.py
       t@@ -193,18 +193,26 @@ class CancelButton(QPushButton):
                self.clicked.connect(dialog.reject)
        
        class MessageBoxMixin:
       +    def question(self, msg, parent=None, title=None):
       +        Yes, No = QMessageBox.Yes, QMessageBox.No
       +        return WindowModalDialog.question(parent or self, title, msg,
       +                                          buttons=Yes|No,
       +                                          defaultButton=No) == Yes
       +
            def show_warning(self, msg, parent=None, title=None):
       -        WindowModalDialog.warning(parent or self, title or _('Warning'), msg)
       +        return WindowModalDialog.warning(parent or self,
       +                                         title or _('Warning'), msg)
        
            def show_error(self, msg, parent=None):
       -        self.show_warning(msg, parent=parent, title=_('Error'))
       +        return self.show_warning(msg, parent=parent, title=_('Error'))
        
            def show_critical(self, msg, parent=None, title=None):
       -        WindowModalDialog.critical(parent or self,
       -                                   title or _('Critical Error'), msg)
       +        return WindowModalDialog.critical(parent or self,
       +                                          title or _('Critical Error'), msg)
        
            def show_message(self, msg, parent=None, title=None):
       -        WindowModalDialog.information(self, title or _('Information'), msg)
       +        return WindowModalDialog.information(self, title or _('Information'),
       +                                             msg)
        
        class WindowModalDialog(QDialog):
            '''Handy wrapper; window modal dialogs are better for our multi-window
       t@@ -216,6 +224,10 @@ class WindowModalDialog(QDialog):
                    self.setWindowTitle(title)
        
            @staticmethod
       +    def question(*args, **kwargs):
       +        return WindowModalDialog.msg_box(QMessageBox.Question, *args, **kwargs)
       +
       +    @staticmethod
            def critical(*args, **kwargs):
                return WindowModalDialog.msg_box(QMessageBox.Critical, *args, **kwargs)
        
   DIR diff --git a/lib/qrscanner.py b/lib/qrscanner.py
       t@@ -12,7 +12,7 @@ proc = None
        def scan_qr(config):
            global proc
            if not zbar:
       -        raise BaseException("\n".join([_("Cannot start QR scanner."),_("The zbar package is not available."),_("On Linux, try 'sudo pip install zbar'")]))
       +        raise RuntimeError("\n".join([_("Cannot start QR scanner."),_("The zbar package is not available."),_("On Linux, try 'sudo pip install zbar'")]))
            if proc is None:
                device = config.get("video_device", "default")
                if device == 'default':
   DIR diff --git a/plugins/keepkey/qt.py b/plugins/keepkey/qt.py
       t@@ -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
       t@@ -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)
       t@@ -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))
       t@@ -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)
       t@@ -182,5 +174,3 @@ class KeepKeyQtHandler:
        
            def dialog_stop(self):
                self.d.hide()
       -
       -
   DIR diff --git a/plugins/trezor/qt.py b/plugins/trezor/qt.py
       t@@ -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
       t@@ -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))
       t@@ -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)
       t@@ -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)