Example #1
0
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     l = QVBoxLayout()
     self.setLayout(l)
     l.addStretch(10)
     self.pi = ProgressIndicator(self, 128)
     l.addWidget(self.pi, alignment=Qt.AlignHCenter)
     self.dummy = QLabel('<h2>\xa0')
     l.addSpacing(10)
     l.addWidget(self.dummy, alignment=Qt.AlignHCenter)
     l.addStretch(10)
     self.text = _('Calculating differences, please wait...')
Example #2
0
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     l = QVBoxLayout()
     self.setLayout(l)
     l.addStretch(10)
     self.pi = ProgressIndicator(self, 128)
     l.addWidget(self.pi, alignment=Qt.AlignHCenter)
     self.dummy = QLabel('<h2>\xa0')
     l.addSpacing(10)
     l.addWidget(self.dummy, alignment=Qt.AlignHCenter)
     l.addStretch(10)
     self.text = _('Calculating differences, please wait...')
Example #3
0
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     l = QVBoxLayout()
     self.setLayout(l)
     l.addStretch(10)
     self.pi = ProgressIndicator(self, 128)
     l.addWidget(self.pi, alignment=Qt.AlignHCenter)
     self.dummy = QLabel('<h2>\xa0')
     l.addSpacing(10)
     l.addWidget(self.dummy, alignment=Qt.AlignHCenter)
     l.addStretch(10)
     self.setVisible(False)
     self.text = ''
Example #4
0
    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        keyboard_shortcuts_button = QPushButton('Keyboard shortcuts...', self)
        keyboard_shortcuts_button.setToolTip(_(
                    'Edit the keyboard shortcuts associated with this plugin'))
        keyboard_shortcuts_button.clicked.connect(self.edit_shortcuts)
        layout.addWidget(keyboard_shortcuts_button)

        reset_confirmation_button = QPushButton(_('Reset disabled &confirmation dialogs'), self)
        reset_confirmation_button.setToolTip(_(
                    'Reset all show me again dialogs for the Find Duplicates plugin'))
        reset_confirmation_button.clicked.connect(self.reset_dialogs)
        layout.addWidget(reset_confirmation_button)
        view_prefs_button = QPushButton('&View library preferences...', self)
        view_prefs_button.setToolTip(_(
                    'View data stored in the library database for this plugin'))
        view_prefs_button.clicked.connect(self.view_prefs)
        layout.addWidget(view_prefs_button)
        layout.addStretch(1)
Example #5
0
    def __init__(self, window, plugin, device_id):
        title = _("%s Settings") % plugin.device
        super(SettingsDialog, self).__init__(window, title)
        self.setMaximumWidth(540)

        devmgr = plugin.device_manager()
        config = devmgr.config
        keystore = window.wallet.get_keystore()
        handler = keystore.handler
        thread = keystore.thread
        # wallet can be None, needn't be window.wallet
        wallet = devmgr.wallet_by_id(device_id)
        hs_rows, hs_cols = (64, 128)

        def invoke_client(method, *args, **kw_args):
            unpair_after = kw_args.pop('unpair_after', False)

            def task():
                client = devmgr.client_by_id(device_id, handler)
                if not client:
                    raise RuntimeError("Device not connected")
                if method:
                    getattr(client, method)(*args, **kw_args)
                if unpair_after:
                    devmgr.unpair_id(device_id)
                return client.features

            thread.add(task, on_success=update)

        def update(features):
            self.features = features
            set_label_enabled()
            bl_hash = features.bootloader_hash.encode('hex')
            bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]])
            noyes = [_("No"), _("Yes")]
            endis = [_("Enable Passphrases"), _("Disable Passphrases")]
            disen = [_("Disabled"), _("Enabled")]
            setchange = [_("Set a PIN"), _("Change PIN")]

            version = "%d.%d.%d" % (features.major_version,
                                    features.minor_version,
                                    features.patch_version)
            coins = ", ".join(coin.coin_name for coin in features.coins)

            device_label.setText(features.label)
            pin_set_label.setText(noyes[features.pin_protection])
            passphrases_label.setText(disen[features.passphrase_protection])
            bl_hash_label.setText(bl_hash)
            label_edit.setText(features.label)
            device_id_label.setText(features.device_id)
            initialized_label.setText(noyes[features.initialized])
            version_label.setText(version)
            coins_label.setText(coins)
            clear_pin_button.setVisible(features.pin_protection)
            clear_pin_warning.setVisible(features.pin_protection)
            pin_button.setText(setchange[features.pin_protection])
            pin_msg.setVisible(not features.pin_protection)
            passphrase_button.setText(endis[features.passphrase_protection])
            language_label.setText(features.language)

        def set_label_enabled():
            label_apply.setEnabled(label_edit.text() != self.features.label)

        def rename():
            invoke_client('change_label', unicode(label_edit.text()))

        def toggle_passphrase():
            title = _("Confirm Toggle Passphrase Protection")
            currently_enabled = self.features.passphrase_protection
            if currently_enabled:
                msg = _("After disabling passphrases, you can only pair this "
                        "Electrum wallet if it had an empty passphrase.  "
                        "If its passphrase was not empty, you will need to "
                        "create a new wallet with the install wizard.  You "
                        "can use this wallet again at any time by re-enabling "
                        "passphrases and entering its passphrase.")
            else:
                msg = _("Your current Electrum wallet can only be used with "
                        "an empty passphrase.  You must create a separate "
                        "wallet with the install wizard for other passphrases "
                        "as each one generates a new set of addresses.")
            msg += "\n\n" + _("Are you sure you want to proceed?")
            if not self.question(msg, title=title):
                return
            invoke_client('toggle_passphrase', unpair_after=currently_enabled)

        def change_homescreen():
            from PIL import Image  # FIXME
            dialog = QFileDialog(self, _("Choose Homescreen"))
            filename = dialog.getOpenFileName()
            if filename:
                im = Image.open(str(filename))
                if im.size != (hs_cols, hs_rows):
                    raise Exception('Image must be 64 x 128 pixels')
                im = im.convert('1')
                pix = im.load()
                img = ''
                for j in range(hs_rows):
                    for i in range(hs_cols):
                        img += '1' if pix[i, j] else '0'
                img = ''.join(
                    chr(int(img[i:i + 8], 2)) for i in range(0, len(img), 8))
                invoke_client('change_homescreen', img)

        def clear_homescreen():
            invoke_client('change_homescreen', '\x00')

        def set_pin():
            invoke_client('set_pin', remove=False)

        def clear_pin():
            invoke_client('set_pin', remove=True)

        def wipe_device():
            if wallet and sum(wallet.get_balance()):
                title = _("Confirm Device Wipe")
                msg = _("Are you SURE you want to wipe the device?\n"
                        "Your wallet still has bitcoins in it!")
                if not self.question(
                        msg, title=title, icon=QMessageBox.Critical):
                    return
            invoke_client('wipe_device', unpair_after=True)

        def slider_moved():
            mins = timeout_slider.sliderPosition()
            timeout_minutes.setText(_("%2d minutes") % mins)

        def slider_released():
            config.set_session_timeout(timeout_slider.sliderPosition() * 60)

        # Information tab
        info_tab = QWidget()
        info_layout = QVBoxLayout(info_tab)
        info_glayout = QGridLayout()
        info_glayout.setColumnStretch(2, 1)
        device_label = QLabel()
        pin_set_label = QLabel()
        passphrases_label = QLabel()
        version_label = QLabel()
        device_id_label = QLabel()
        bl_hash_label = QLabel()
        bl_hash_label.setWordWrap(True)
        coins_label = QLabel()
        coins_label.setWordWrap(True)
        language_label = QLabel()
        initialized_label = QLabel()
        rows = [
            (_("Device Label"), device_label),
            (_("PIN set"), pin_set_label),
            (_("Passphrases"), passphrases_label),
            (_("Firmware Version"), version_label),
            (_("Device ID"), device_id_label),
            (_("Bootloader Hash"), bl_hash_label),
            (_("Supported Coins"), coins_label),
            (_("Language"), language_label),
            (_("Initialized"), initialized_label),
        ]
        for row_num, (label, widget) in enumerate(rows):
            info_glayout.addWidget(QLabel(label), row_num, 0)
            info_glayout.addWidget(widget, row_num, 1)
        info_layout.addLayout(info_glayout)

        # Settings tab
        settings_tab = QWidget()
        settings_layout = QVBoxLayout(settings_tab)
        settings_glayout = QGridLayout()

        # Settings tab - Label
        label_msg = QLabel(
            _("Name this %s.  If you have mutiple devices "
              "their labels help distinguish them.") % plugin.device)
        label_msg.setWordWrap(True)
        label_label = QLabel(_("Device Label"))
        label_edit = QLineEdit()
        label_edit.setMinimumWidth(150)
        label_edit.setMaxLength(plugin.MAX_LABEL_LEN)
        label_apply = QPushButton(_("Apply"))
        label_apply.clicked.connect(rename)
        label_edit.textChanged.connect(set_label_enabled)
        settings_glayout.addWidget(label_label, 0, 0)
        settings_glayout.addWidget(label_edit, 0, 1, 1, 2)
        settings_glayout.addWidget(label_apply, 0, 3)
        settings_glayout.addWidget(label_msg, 1, 1, 1, -1)

        # Settings tab - PIN
        pin_label = QLabel(_("PIN Protection"))
        pin_button = QPushButton()
        pin_button.clicked.connect(set_pin)
        settings_glayout.addWidget(pin_label, 2, 0)
        settings_glayout.addWidget(pin_button, 2, 1)
        pin_msg = QLabel(
            _("PIN protection is strongly recommended.  "
              "A PIN is your only protection against someone "
              "stealing your bitcoins if they obtain physical "
              "access to your %s.") % plugin.device)
        pin_msg.setWordWrap(True)
        pin_msg.setStyleSheet("color: red")
        settings_glayout.addWidget(pin_msg, 3, 1, 1, -1)

        # Settings tab - Homescreen
        if plugin.device != 'KeepKey':  # Not yet supported by KK firmware
            homescreen_layout = QHBoxLayout()
            homescreen_label = QLabel(_("Homescreen"))
            homescreen_change_button = QPushButton(_("Change..."))
            homescreen_clear_button = QPushButton(_("Reset"))
            homescreen_change_button.clicked.connect(change_homescreen)
            homescreen_clear_button.clicked.connect(clear_homescreen)
            homescreen_msg = QLabel(
                _("You can set the homescreen on your "
                  "device to personalize it.  You must "
                  "choose a %d x %d monochrome black and "
                  "white image.") % (hs_rows, hs_cols))
            homescreen_msg.setWordWrap(True)
            settings_glayout.addWidget(homescreen_label, 4, 0)
            settings_glayout.addWidget(homescreen_change_button, 4, 1)
            settings_glayout.addWidget(homescreen_clear_button, 4, 2)
            settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1)

        # Settings tab - Session Timeout
        timeout_label = QLabel(_("Session Timeout"))
        timeout_minutes = QLabel()
        timeout_slider = QSlider(Qt.Horizontal)
        timeout_slider.setRange(1, 60)
        timeout_slider.setSingleStep(1)
        timeout_slider.setTickInterval(5)
        timeout_slider.setTickPosition(QSlider.TicksBelow)
        timeout_slider.setTracking(True)
        timeout_msg = QLabel(
            _("Clear the session after the specified period "
              "of inactivity.  Once a session has timed out, "
              "your PIN and passphrase (if enabled) must be "
              "re-entered to use the device."))
        timeout_msg.setWordWrap(True)
        timeout_slider.setSliderPosition(config.get_session_timeout() // 60)
        slider_moved()
        timeout_slider.valueChanged.connect(slider_moved)
        timeout_slider.sliderReleased.connect(slider_released)
        settings_glayout.addWidget(timeout_label, 6, 0)
        settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3)
        settings_glayout.addWidget(timeout_minutes, 6, 4)
        settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1)
        settings_layout.addLayout(settings_glayout)
        settings_layout.addStretch(1)

        # Advanced tab
        advanced_tab = QWidget()
        advanced_layout = QVBoxLayout(advanced_tab)
        advanced_glayout = QGridLayout()

        # Advanced tab - clear PIN
        clear_pin_button = QPushButton(_("Disable PIN"))
        clear_pin_button.clicked.connect(clear_pin)
        clear_pin_warning = QLabel(
            _("If you disable your PIN, anyone with physical access to your "
              "%s device can spend your bitcoins.") % plugin.device)
        clear_pin_warning.setWordWrap(True)
        clear_pin_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(clear_pin_button, 0, 2)
        advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5)

        # Advanced tab - toggle passphrase protection
        passphrase_button = QPushButton()
        passphrase_button.clicked.connect(toggle_passphrase)
        passphrase_msg = WWLabel(PASSPHRASE_HELP)
        passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN)
        passphrase_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(passphrase_button, 3, 2)
        advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5)
        advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5)

        # Advanced tab - wipe device
        wipe_device_button = QPushButton(_("Wipe Device"))
        wipe_device_button.clicked.connect(wipe_device)
        wipe_device_msg = QLabel(
            _("Wipe the device, removing all data from it.  The firmware "
              "is left unchanged."))
        wipe_device_msg.setWordWrap(True)
        wipe_device_warning = QLabel(
            _("Only wipe a device if you have the recovery seed written down "
              "and the device wallet(s) are empty, otherwise the bitcoins "
              "will be lost forever."))
        wipe_device_warning.setWordWrap(True)
        wipe_device_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(wipe_device_button, 6, 2)
        advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5)
        advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5)
        advanced_layout.addLayout(advanced_glayout)
        advanced_layout.addStretch(1)

        tabs = QTabWidget(self)
        tabs.addTab(info_tab, _("Information"))
        tabs.addTab(settings_tab, _("Settings"))
        tabs.addTab(advanced_tab, _("Advanced"))
        dialog_vbox = QVBoxLayout(self)
        dialog_vbox.addWidget(tabs)
        dialog_vbox.addLayout(Buttons(CloseButton(self)))

        # Update information
        invoke_client(None)
Example #6
0
    def __init__(self, window, plugin, device_id):
        title = _("%s Settings") % plugin.device
        super(SettingsDialog, self).__init__(window, title)
        self.setMaximumWidth(540)

        devmgr = plugin.device_manager()
        handler = window.wallet.handler
        thread = window.wallet.thread
        # wallet can be None, needn't be window.wallet
        wallet = devmgr.wallet_by_id(device_id)
        hs_rows, hs_cols = (64, 128)
        self.current_label=None

        def invoke_client(method, *args, **kw_args):
            unpair_after = kw_args.pop('unpair_after', False)

            def task():
                client = devmgr.client_by_id(device_id, handler)
                if not client:
                    raise RuntimeError("Device not connected")
                if method:
                    getattr(client, method)(*args, **kw_args)
                if unpair_after:
                    devmgr.unpair_id(device_id)
                return client.features

            thread.add(task, on_success=update)

        def update(features):
            self.current_label = features.label
            set_label_enabled()
            bl_hash = features.bootloader_hash.encode('hex')
            bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]])
            noyes = [_("No"), _("Yes")]
            endis = [_("Enable Passphrases"), _("Disable Passphrases")]
            disen = [_("Disabled"), _("Enabled")]
            setchange = [_("Set a PIN"), _("Change PIN")]

            version = "%d.%d.%d" % (features.major_version,
                                    features.minor_version,
                                    features.patch_version)
            coins = ", ".join(coin.coin_name for coin in features.coins)

            device_label.setText(features.label)
            pin_set_label.setText(noyes[features.pin_protection])
            passphrases_label.setText(disen[features.passphrase_protection])
            bl_hash_label.setText(bl_hash)
            label_edit.setText(features.label)
            device_id_label.setText(features.device_id)
            initialized_label.setText(noyes[features.initialized])
            version_label.setText(version)
            coins_label.setText(coins)
            clear_pin_button.setVisible(features.pin_protection)
            clear_pin_warning.setVisible(features.pin_protection)
            pin_button.setText(setchange[features.pin_protection])
            pin_msg.setVisible(not features.pin_protection)
            passphrase_button.setText(endis[features.passphrase_protection])
            language_label.setText(features.language)

        def set_label_enabled():
            label_apply.setEnabled(label_edit.text() != self.current_label)

        def rename():
            invoke_client('change_label', unicode(label_edit.text()))

        def toggle_passphrase():
            title = _("Confirm Toggle Passphrase Protection")
            msg = _("This will cause your Electrum wallet to be unpaired "
                    "unless your passphrase was or will be empty.\n\n"
                    "This is because addresses will no "
                    "longer correspond to those used by your %s.\n\n"
                    "You will need to create a new Electrum wallet "
                    "with the install wizard so that they match.\n\n"
                    "Are you sure you want to proceed?") % plugin.device
            if not self.question(msg, title=title):
                return
            invoke_client('toggle_passphrase', unpair_after=True)

        def change_homescreen():
            from PIL import Image  # FIXME
            dialog = QFileDialog(self, _("Choose Homescreen"))
            filename = dialog.getOpenFileName()
            if filename:
                im = Image.open(str(filename))
                if im.size != (hs_cols, hs_rows):
                    raise Exception('Image must be 64 x 128 pixels')
                im = im.convert('1')
                pix = im.load()
                img = ''
                for j in range(hs_rows):
                    for i in range(hs_cols):
                        img += '1' if pix[i, j] else '0'
                img = ''.join(chr(int(img[i:i + 8], 2))
                              for i in range(0, len(img), 8))
                invoke_client('change_homescreen', img)

        def clear_homescreen():
            invoke_client('change_homescreen', '\x00')

        def set_pin():
            invoke_client('set_pin', remove=False)

        def clear_pin():
            invoke_client('set_pin', remove=True)

        def wipe_device():
            if wallet and sum(wallet.get_balance()):
                title = _("Confirm Device Wipe")
                msg = _("Are you SURE you want to wipe the device?\n"
                        "Your wallet still has bitcoins in it!")
                if not self.question(msg, title=title,
                                     icon=QMessageBox.Critical):
                    return
            invoke_client('wipe_device', unpair_after=True)

        def slider_moved():
            mins = timeout_slider.sliderPosition()
            timeout_minutes.setText(_("%2d minutes") % mins)

        def slider_released():
            seconds = timeout_slider.sliderPosition() * 60
            wallet.set_session_timeout(seconds)

        # Information tab
        info_tab = QWidget()
        info_layout = QVBoxLayout(info_tab)
        info_glayout = QGridLayout()
        info_glayout.setColumnStretch(2, 1)
        device_label = QLabel()
        pin_set_label = QLabel()
        passphrases_label = QLabel()
        version_label = QLabel()
        device_id_label = QLabel()
        bl_hash_label = QLabel()
        bl_hash_label.setWordWrap(True)
        coins_label = QLabel()
        coins_label.setWordWrap(True)
        language_label = QLabel()
        initialized_label = QLabel()
        rows = [
            (_("Device Label"), device_label),
            (_("PIN set"), pin_set_label),
            (_("Passphrases"), passphrases_label),
            (_("Firmware Version"), version_label),
            (_("Device ID"), device_id_label),
            (_("Bootloader Hash"), bl_hash_label),
            (_("Supported Coins"), coins_label),
            (_("Language"), language_label),
            (_("Initialized"), initialized_label),
        ]
        for row_num, (label, widget) in enumerate(rows):
            info_glayout.addWidget(QLabel(label), row_num, 0)
            info_glayout.addWidget(widget, row_num, 1)
        info_layout.addLayout(info_glayout)

        # Settings tab
        settings_tab = QWidget()
        settings_layout = QVBoxLayout(settings_tab)
        settings_glayout = QGridLayout()

        # Settings tab - Label
        label_msg = QLabel(_("Name this %s.  If you have mutiple devices "
                             "their labels help distinguish them.")
                           % plugin.device)
        label_msg.setWordWrap(True)
        label_label = QLabel(_("Device Label"))
        label_edit = QLineEdit()
        label_edit.setMinimumWidth(150)
        label_edit.setMaxLength(plugin.MAX_LABEL_LEN)
        label_apply = QPushButton(_("Apply"))
        label_apply.clicked.connect(rename)
        label_edit.textChanged.connect(set_label_enabled)
        settings_glayout.addWidget(label_label, 0, 0)
        settings_glayout.addWidget(label_edit, 0, 1, 1, 2)
        settings_glayout.addWidget(label_apply, 0, 3)
        settings_glayout.addWidget(label_msg, 1, 1, 1, -1)

        # Settings tab - PIN
        pin_label = QLabel(_("PIN Protection"))
        pin_button = QPushButton()
        pin_button.clicked.connect(set_pin)
        settings_glayout.addWidget(pin_label, 2, 0)
        settings_glayout.addWidget(pin_button, 2, 1)
        pin_msg = QLabel(_("PIN protection is strongly recommended.  "
                           "A PIN is your only protection against someone "
                           "stealing your bitcoins if they obtain physical "
                           "access to your %s.") % plugin.device)
        pin_msg.setWordWrap(True)
        pin_msg.setStyleSheet("color: red")
        settings_glayout.addWidget(pin_msg, 3, 1, 1, -1)

        # Settings tab - Homescreen
        if plugin.device != 'KeepKey':   # Not yet supported by KK firmware
            homescreen_layout = QHBoxLayout()
            homescreen_label = QLabel(_("Homescreen"))
            homescreen_change_button = QPushButton(_("Change..."))
            homescreen_clear_button = QPushButton(_("Reset"))
            homescreen_change_button.clicked.connect(change_homescreen)
            homescreen_clear_button.clicked.connect(clear_homescreen)
            homescreen_msg = QLabel(_("You can set the homescreen on your "
                                      "device to personalize it.  You must "
                                      "choose a %d x %d monochrome black and "
                                      "white image.") % (hs_rows, hs_cols))
            homescreen_msg.setWordWrap(True)
            settings_glayout.addWidget(homescreen_label, 4, 0)
            settings_glayout.addWidget(homescreen_change_button, 4, 1)
            settings_glayout.addWidget(homescreen_clear_button, 4, 2)
            settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1)

        # Settings tab - Session Timeout
        if wallet:
            timeout_label = QLabel(_("Session Timeout"))
            timeout_minutes = QLabel()
            timeout_slider = QSlider(Qt.Horizontal)
            timeout_slider.setRange(1, 60)
            timeout_slider.setSingleStep(1)
            timeout_slider.setTickInterval(5)
            timeout_slider.setTickPosition(QSlider.TicksBelow)
            timeout_slider.setTracking(True)
            timeout_msg = QLabel(
                _("Clear the session after the specified period "
                  "of inactivity.  Once a session has timed out, "
                  "your PIN and passphrase (if enabled) must be "
                  "re-entered to use the device."))
            timeout_msg.setWordWrap(True)
            timeout_slider.setSliderPosition(wallet.session_timeout // 60)
            slider_moved()
            timeout_slider.valueChanged.connect(slider_moved)
            timeout_slider.sliderReleased.connect(slider_released)
            settings_glayout.addWidget(timeout_label, 6, 0)
            settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3)
            settings_glayout.addWidget(timeout_minutes, 6, 4)
            settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1)
        settings_layout.addLayout(settings_glayout)
        settings_layout.addStretch(1)

        # Advanced tab
        advanced_tab = QWidget()
        advanced_layout = QVBoxLayout(advanced_tab)
        advanced_glayout = QGridLayout()

        # Advanced tab - clear PIN
        clear_pin_button = QPushButton(_("Disable PIN"))
        clear_pin_button.clicked.connect(clear_pin)
        clear_pin_warning = QLabel(
            _("If you disable your PIN, anyone with physical access to your "
              "%s device can spend your bitcoins.") % plugin.device)
        clear_pin_warning.setWordWrap(True)
        clear_pin_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(clear_pin_button, 0, 2)
        advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5)

        # Advanced tab - toggle passphrase protection
        passphrase_button = QPushButton()
        passphrase_button.clicked.connect(toggle_passphrase)
        passphrase_msg = WWLabel(PASSPHRASE_HELP)
        passphrase_warning = WWLabel(PASSPHRASE_NOT_PIN)
        passphrase_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(passphrase_button, 3, 2)
        advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5)
        advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5)

        # Advanced tab - wipe device
        wipe_device_button = QPushButton(_("Wipe Device"))
        wipe_device_button.clicked.connect(wipe_device)
        wipe_device_msg = QLabel(
            _("Wipe the device, removing all data from it.  The firmware "
              "is left unchanged."))
        wipe_device_msg.setWordWrap(True)
        wipe_device_warning = QLabel(
            _("Only wipe a device if you have the recovery seed written down "
              "and the device wallet(s) are empty, otherwise the bitcoins "
              "will be lost forever."))
        wipe_device_warning.setWordWrap(True)
        wipe_device_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(wipe_device_button, 6, 2)
        advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5)
        advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5)
        advanced_layout.addLayout(advanced_glayout)
        advanced_layout.addStretch(1)

        tabs = QTabWidget(self)
        tabs.addTab(info_tab, _("Information"))
        tabs.addTab(settings_tab, _("Settings"))
        tabs.addTab(advanced_tab, _("Advanced"))
        dialog_vbox = QVBoxLayout(self)
        dialog_vbox.addWidget(tabs)
        dialog_vbox.addLayout(Buttons(CloseButton(self)))

        # Update information
        invoke_client(None)
Example #7
0
    def __init__(self, window, plugin):
        self.plugin = plugin
        self.window = window  # The main electrum window
        title = _("%s Settings") % plugin.device
        super(SettingsDialog, self).__init__(window, title)
        self.setMaximumWidth(540)
        hs_rows, hs_cols = (64, 128)

        def get_client(lookup=DeviceMgr.PAIRED):
            return self.plugin.get_client(wallet, lookup)

        def update():
            features = get_client(DeviceMgr.PAIRED).features
            self.features = features
            # The above was for outer scopes.  Now the real logic.
            set_label_enabled()
            bl_hash = features.bootloader_hash.encode('hex')
            bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]])
            noyes = [_("No"), _("Yes")]
            endis = [_("Enable Passphrases"), _("Disable Passphrases")]
            setchange = [_("Set a PIN"), _("Change PIN")]

            version = "%d.%d.%d" % (features.major_version,
                                    features.minor_version,
                                    features.patch_version)
            coins = ", ".join(coin.coin_name for coin in features.coins)

            device_label.setText(features.label)
            pin_set_label.setText(noyes[features.pin_protection])
            bl_hash_label.setText(bl_hash)
            label_edit.setText(features.label)
            device_id_label.setText(features.device_id)
            initialized_label.setText(noyes[features.initialized])
            version_label.setText(version)
            coins_label.setText(coins)
            clear_pin_button.setVisible(features.pin_protection)
            clear_pin_warning.setVisible(features.pin_protection)
            pin_button.setText(setchange[features.pin_protection])
            pin_msg.setVisible(not features.pin_protection)
            passphrase_button.setText(endis[features.passphrase_protection])

            language_label.setText(features.language)

        def set_label_enabled():
            label_apply.setEnabled(label_edit.text() != self.features.label)

        def rename():
            get_client().change_label(unicode(label_edit.text()))
            update()

        def toggle_passphrase():
            title = _("Confirm Toggle Passphrase Protection")
            msg = _("This will cause your Electrum wallet to be unpaired "
                    "unless your passphrase was or will be empty.\n\n"
                    "This is because addresses will no "
                    "longer correspond to those used by your %s.\n\n"
                    "You will need to create a new Electrum wallet "
                    "with the install wizard so that they match.\n\n"
                    "Are you sure you want to proceed?") % plugin.device
            if not self.question(msg, title=title):
                return
            get_client().toggle_passphrase()
            self.device_manager().close_wallet(wallet)  # Unpair
            update()

        def change_homescreen():
            dialog = QFileDialog(self, _("Choose Homescreen"))
            filename = dialog.getOpenFileName()
            if filename:
                im = Image.open(str(filename))
                if im.size != (hs_cols, hs_rows):
                    raise Exception('Image must be 64 x 128 pixels')
                im = im.convert('1')
                pix = im.load()
                img = ''
                for j in range(hs_rows):
                    for i in range(hs_cols):
                        img += '1' if pix[i, j] else '0'
                img = ''.join(chr(int(img[i:i + 8], 2))
                              for i in range(0, len(img), 8))
                get_client().change_homescreen(img)

        def clear_homescreen():
            get_client().change_homescreen('\x00')

        def set_pin(remove=False):
            get_client().set_pin(remove=remove)
            update()

        def clear_pin():
            set_pin(remove=True)

        def wipe_device():
            # FIXME: cannot yet wipe a device that is only plugged in
            if sum(wallet.get_balance()):
                title = _("Confirm Device Wipe")
                msg = _("Are you SURE you want to wipe the device?\n"
                        "Your wallet still has bitcoins in it!")
                if not self.question(msg, title=title,
                                     icon=QMessageBox.Critical):
                    return
            # Note: we use PRESENT so that a user who has forgotten
            # their PIN is not prevented from wiping their device
            get_client(DeviceMgr.PRESENT).wipe_device()
            self.device_manager().close_wallet(wallet)
            update()

        def slider_moved():
            mins = timeout_slider.sliderPosition()
            timeout_minutes.setText(_("%2d minutes") % mins)

        wallet = window.wallet
        handler = wallet.handler
        device = plugin.device
        dialog_vbox = QVBoxLayout(self)

        # Information tab
        info_tab = QWidget()
        info_layout = QVBoxLayout(info_tab)
        info_glayout = QGridLayout()
        info_glayout.setColumnStretch(2, 1)
        device_label = QLabel()
        pin_set_label = QLabel()
        version_label = QLabel()
        device_id_label = QLabel()
        bl_hash_label = QLabel()
        bl_hash_label.setWordWrap(True)
        coins_label = QLabel()
        coins_label.setWordWrap(True)
        language_label = QLabel()
        initialized_label = QLabel()
        rows = [
            (_("Device Label"), device_label),
            (_("PIN set"), pin_set_label),
            (_("Firmware Version"), version_label),
            (_("Serial Number"), device_id_label),
            (_("Bootloader Hash"), bl_hash_label),
            (_("Supported Coins"), coins_label),
            (_("Language"), language_label),
            (_("Initialized"), initialized_label),
        ]
        for row_num, (label, widget) in enumerate(rows):
            info_glayout.addWidget(QLabel(label), row_num, 0)
            info_glayout.addWidget(widget, row_num, 1)
        info_layout.addLayout(info_glayout)

        # Settings tab
        settings_tab = QWidget()
        settings_layout = QVBoxLayout(settings_tab)
        settings_glayout = QGridLayout()
        #settings_glayout.setColumnStretch(3, 1)

        # Settings tab - Label
        label_msg = QLabel(_("Name this %s.  If you have mutiple devices "
                             "their labels help distinguish them.")
                           % plugin.device)
        label_msg.setWordWrap(True)
        label_label = QLabel(_("Device Label"))
        label_edit = QLineEdit()
        label_edit.setMinimumWidth(150)
        label_edit.setMaxLength(self.plugin.MAX_LABEL_LEN)
        label_apply = QPushButton(_("Apply"))
        label_apply.clicked.connect(rename)
        label_edit.textChanged.connect(set_label_enabled)
        settings_glayout.addWidget(label_label, 0, 0)
        settings_glayout.addWidget(label_edit, 0, 1, 1, 2)
        settings_glayout.addWidget(label_apply, 0, 3)
        settings_glayout.addWidget(label_msg, 1, 1, 1, -1)

        # Settings tab - PIN
        pin_label = QLabel(_("PIN Protection"))
        pin_button = QPushButton()
        pin_button.clicked.connect(set_pin)
        settings_glayout.addWidget(pin_label, 2, 0)
        settings_glayout.addWidget(pin_button, 2, 1)
        pin_msg = QLabel(_("PIN protection is strongly recommended.  "
                           "A PIN is your only protection against someone "
                           "stealing your bitcoins if they obtain physical "
                           "access to your %s.") % plugin.device)
        pin_msg.setWordWrap(True)
        pin_msg.setStyleSheet("color: red")
        settings_glayout.addWidget(pin_msg, 3, 1, 1, -1)
        settings_layout.addLayout(settings_glayout)

        # Settings tab - Homescreen
        homescreen_layout = QHBoxLayout()
        homescreen_label = QLabel(_("Homescreen"))
        homescreen_change_button = QPushButton(_("Change..."))
        homescreen_clear_button = QPushButton(_("Reset"))
        homescreen_change_button.clicked.connect(change_homescreen)
        homescreen_clear_button.clicked.connect(clear_homescreen)
        homescreen_msg = QLabel(_("You can set the homescreen on your device "
                                  "to personalize it.  You must choose a "
                                  "%d x %d monochrome black and white image.")
                                % (hs_rows, hs_cols))
        homescreen_msg.setWordWrap(True)
        settings_glayout.addWidget(homescreen_label, 4, 0)
        settings_glayout.addWidget(homescreen_change_button, 4, 1)
        settings_glayout.addWidget(homescreen_clear_button, 4, 2)
        settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1)

        # Settings tab - Session Timeout
        timeout_label = QLabel(_("Session Timeout"))
        timeout_minutes = QLabel()
        timeout_slider = self.slider = QSlider(Qt.Horizontal)
        timeout_slider.setRange(1, 60)
        timeout_slider.setSingleStep(1)
        timeout_slider.setSliderPosition(wallet.session_timeout // 60)
        timeout_slider.setTickInterval(5)
        timeout_slider.setTickPosition(QSlider.TicksBelow)
        timeout_slider.setTracking(True)
        timeout_slider.valueChanged.connect(slider_moved)
        timeout_msg = QLabel(_("Clear the session after the specified period "
                               "of inactivity.  Once a session has timed out, "
                               "your PIN and passphrase (if enabled) must be "
                               "re-entered to use the device."))
        timeout_msg.setWordWrap(True)
        settings_glayout.addWidget(timeout_label, 6, 0)
        settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3)
        settings_glayout.addWidget(timeout_minutes, 6, 4)
        settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1)

        # Advanced tab
        advanced_tab = QWidget()
        advanced_layout = QVBoxLayout(advanced_tab)
        advanced_glayout = QGridLayout()

        # Advanced tab - clear PIN
        clear_pin_button = QPushButton(_("Disable PIN"))
        clear_pin_button.clicked.connect(clear_pin)
        clear_pin_warning = QLabel(_("If you disable your PIN, anyone with "
                                     "physical access to your %s device can "
                                     "spend your bitcoins.") % plugin.device)
        clear_pin_warning.setWordWrap(True)
        clear_pin_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(clear_pin_button, 0, 2)
        advanced_glayout.addWidget(clear_pin_warning, 1, 0, 1, 5)

        # Advanced tab - toggle passphrase protection
        passphrase_button = QPushButton()
        passphrase_button.clicked.connect(toggle_passphrase)
        passphrase_msg = QLabel(
            _("Passphrases allow you to access new wallets, each "
              "hidden behind a particular case-sensitive passphrase.  You "
              "need to create a separate Electrum wallet for each passphrase "
              "you use as they each generate different addresses.  Changing "
              "your passphrase does not lose other wallets, each is still "
              "accessible behind its own passphrase."))
        passphrase_msg.setWordWrap(True)
        passphrase_warning = QLabel(
            _("If you forget a passphrase you will be unable to access any "
              "bitcoins in the wallet behind it.  A passphrase is not a PIN. "
              "Only change this if you are sure you understand it."))
        passphrase_warning.setWordWrap(True)
        passphrase_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(passphrase_button, 3, 2)
        advanced_glayout.addWidget(passphrase_msg, 4, 0, 1, 5)
        advanced_glayout.addWidget(passphrase_warning, 5, 0, 1, 5)

        # Advanced tab - wipe device
        wipe_device_button = QPushButton(_("Wipe Device"))
        wipe_device_button.clicked.connect(wipe_device)
        wipe_device_msg = QLabel(
            _("Wipe the device, removing all data from it.  The firmware "
              "is left unchanged."))
        wipe_device_msg.setWordWrap(True)
        wipe_device_warning = QLabel(
            _("Only wipe a device if you have the recovery seed written down "
              "and the device wallet(s) are empty, otherwise the bitcoins "
              "will be lost forever."))
        wipe_device_warning.setWordWrap(True)
        wipe_device_warning.setStyleSheet("color: red")
        advanced_glayout.addWidget(wipe_device_button, 6, 2)
        advanced_glayout.addWidget(wipe_device_msg, 7, 0, 1, 5)
        advanced_glayout.addWidget(wipe_device_warning, 8, 0, 1, 5)
        advanced_layout.addLayout(advanced_glayout)
        advanced_layout.addStretch(1)

        tabs = QTabWidget(self)
        tabs.addTab(info_tab, _("Information"))
        tabs.addTab(settings_tab, _("Settings"))
        tabs.addTab(advanced_tab, _("Advanced"))

        # Update information and then connect change slots
        update()
        slider_moved()

        dialog_vbox.addWidget(tabs)
        dialog_vbox.addLayout(Buttons(CloseButton(self)))
Example #8
0
    def request_trezor_init_settings(self, method, device):
        wizard = self.win

        vbox = QVBoxLayout()
        main_label = QLabel(_("Initialization settings for your %s:") % device)
        vbox.addWidget(main_label)
        OK_button = OkButton(wizard, _('Next'))

        def clean_text(widget):
            text = unicode(widget.toPlainText()).strip()
            return ' '.join(text.split())

        if method in [TIM_NEW, TIM_RECOVER]:
            gb = QGroupBox()
            vbox1 = QVBoxLayout()
            gb.setLayout(vbox1)
            vbox.addWidget(gb)
            gb.setTitle(_("Select your seed length:"))
            choices = [
                _("12 words"),
                _("18 words"),
                _("24 words"),
            ]
            bg = QButtonGroup()
            for i, choice in enumerate(choices):
                rb = QRadioButton(gb)
                rb.setText(choice)
                bg.addButton(rb)
                bg.setId(rb, i)
                vbox1.addWidget(rb)
                rb.setChecked(True)
            cb_pin = QCheckBox(_('Enable PIN protection'))
            cb_pin.setChecked(True)
        else:
            text = QTextEdit()
            text.setMaximumHeight(60)
            if method == TIM_MNEMONIC:
                msg = _("Enter your BIP39 mnemonic:")
            else:
                msg = _("Enter the master private key beginning with xprv:")
                def set_enabled():
                    OK_button.setEnabled(Wallet.is_xprv(clean_text(text)))
                text.textChanged.connect(set_enabled)
                OK_button.setEnabled(False)

            vbox.addWidget(QLabel(msg))
            vbox.addWidget(text)
            pin = QLineEdit()
            pin.setValidator(QRegExpValidator(QRegExp('[1-9]{0,10}')))
            pin.setMaximumWidth(100)
            hbox_pin = QHBoxLayout()
            hbox_pin.addWidget(QLabel(_("Enter your PIN (digits 1-9):")))
            hbox_pin.addWidget(pin)
            hbox_pin.addStretch(1)

        label = QLabel(_("Enter a label to name your device:"))
        name = QLineEdit()
        hl = QHBoxLayout()
        hl.addWidget(label)
        hl.addWidget(name)
        hl.addStretch(1)
        vbox.addLayout(hl)

        if method in [TIM_NEW, TIM_RECOVER]:
            vbox.addWidget(cb_pin)
        else:
            vbox.addLayout(hbox_pin)

        cb_phrase = QCheckBox(_('Enable Passphrase protection'))
        cb_phrase.setChecked(False)
        vbox.addWidget(cb_phrase)

        vbox.addStretch(1)
        vbox.addLayout(Buttons(CancelButton(wizard), OK_button))

        wizard.set_layout(vbox)
        if not wizard.exec_():
            raise UserCancelled

        if method in [TIM_NEW, TIM_RECOVER]:
            item = bg.checkedId()
            pin = cb_pin.isChecked()
        else:
            item = ' '.join(str(clean_text(text)).split())
            pin = str(pin.text())

        return (item, unicode(name.text()), pin, cb_phrase.isChecked())
Example #9
0
    def __init__(self, plugin_action):
        QWidget.__init__(self)
        self.plugin_action = plugin_action
        layout = QVBoxLayout(self)
        self.setLayout(layout)

        c = plugin_prefs[STORE_NAME]
        avail_columns = self.get_custom_columns()
        library_config = get_library_config(self.plugin_action.gui.current_db)
        pages_algorithm = library_config.get(KEY_PAGES_ALGORITHM, DEFAULT_LIBRARY_VALUES[KEY_PAGES_ALGORITHM])
        button_default = c.get(KEY_BUTTON_DEFAULT, DEFAULT_STORE_VALUES[KEY_BUTTON_DEFAULT])
        # Fudge the button default to cater for the options no longer supported by plugin as of 1.5
        if button_default in ['Estimate', 'EstimatePage', 'EstimateWord']:
            button_default = 'Estimate'
        else:
            button_default = 'Goodreads'
        overwrite_existing = c.get(KEY_OVERWRITE_EXISTING, DEFAULT_STORE_VALUES[KEY_OVERWRITE_EXISTING])

        # --- Pages ---
        page_group_box = QGroupBox('Page count options:', self)
        layout.addWidget(page_group_box)
        page_group_box_layout = QGridLayout()
        page_group_box.setLayout(page_group_box_layout)

        page_column_label = QLabel('&Custom column:', self)
        page_column_label.setToolTip('Leave this blank if you do not want to count pages')
        page_col = library_config.get(KEY_PAGES_CUSTOM_COLUMN, '')
        self.page_column_combo = CustomColumnComboBox(self, avail_columns, page_col)
        page_column_label.setBuddy(self.page_column_combo)
        page_group_box_layout.addWidget(page_column_label, 0, 0, 1, 1)
        page_group_box_layout.addWidget(self.page_column_combo, 0, 1, 1, 2)

        page_algorithm_label = QLabel('&Algorithm:', self)
        page_algorithm_label.setToolTip('Choose which algorithm to use if you have specified a page count column')
        self.page_algorithm_combo = AlgorithmComboBox(self, PAGE_ALGORITHMS, pages_algorithm)
        page_algorithm_label.setBuddy(self.page_algorithm_combo)
        page_group_box_layout.addWidget(page_algorithm_label, 1, 0, 1, 1)
        page_group_box_layout.addWidget(self.page_algorithm_combo, 1, 1, 1, 2)

        # --- Words ---
        layout.addSpacing(5)
        word_group_box = QGroupBox('Word count options:', self)
        layout.addWidget(word_group_box)
        word_group_box_layout = QGridLayout()
        word_group_box.setLayout(word_group_box_layout)

        word_column_label = QLabel('C&ustom column:', self)
        word_column_label.setToolTip('Leave this blank if you do not want to count words')
        word_col = library_config.get(KEY_WORDS_CUSTOM_COLUMN, '')
        self.word_column_combo = CustomColumnComboBox(self, avail_columns, word_col)
        word_column_label.setBuddy(self.word_column_combo)
        word_group_box_layout.addWidget(word_column_label, 0, 0, 1, 1)
        word_group_box_layout.addWidget(self.word_column_combo, 0, 1, 1, 2)

        # --- Readability ---
        layout.addSpacing(5)
        readability_group_box = QGroupBox('Readability options:', self)
        layout.addWidget(readability_group_box)
        readability_layout = QGridLayout()
        readability_group_box.setLayout(readability_layout)

        readability_label = QLabel('Readability statistics available are <a href="http://en.wikipedia.org/wiki/Flesch–Kincaid_readability_test">Flesch-Kincaid</a> '
                                   'or <a href="http://en.wikipedia.org/wiki/Gunning_fog_index">Gunning Fog Index</a>.', self)
        readability_layout.addWidget(readability_label, 0, 0, 1, 3)
        readability_label.linkActivated.connect(self._link_activated)

        flesch_reading_column_label = QLabel('&Flesch Reading Ease:', self)
        flesch_reading_column_label.setToolTip('Specify the custom column to store a computed Flesch Reading Ease score.\n'
                                     'Leave this blank if you do not want to calculate it')
        flesch_reading_col = library_config.get(KEY_FLESCH_READING_CUSTOM_COLUMN, '')
        self.flesch_reading_column_combo = CustomColumnComboBox(self, avail_columns, flesch_reading_col)
        flesch_reading_column_label.setBuddy(self.flesch_reading_column_combo)
        readability_layout.addWidget(flesch_reading_column_label, 1, 0, 1, 1)
        readability_layout.addWidget(self.flesch_reading_column_combo, 1, 1, 1, 2)

        flesch_grade_column_label = QLabel('Flesch-&Kincaid Grade:', self)
        flesch_grade_column_label.setToolTip('Specify the custom column to store a computed Flesch-Kincaid Grade Level score.\n'
                                     'Leave this blank if you do not want to calculate it')
        flesch_grade_col = library_config.get(KEY_FLESCH_GRADE_CUSTOM_COLUMN, '')
        self.flesch_grade_column_combo = CustomColumnComboBox(self, avail_columns, flesch_grade_col)
        flesch_grade_column_label.setBuddy(self.flesch_grade_column_combo)
        readability_layout.addWidget(flesch_grade_column_label, 2, 0, 1, 1)
        readability_layout.addWidget(self.flesch_grade_column_combo, 2, 1, 1, 2)

        gunning_fog_column_label = QLabel('&Gunning Fox Index:', self)
        gunning_fog_column_label.setToolTip('Specify the custom column to store a computed Gunning Fog Index score.\n'
                                     'Leave this blank if you do not want to calculate it')
        gunning_fog_col = library_config.get(KEY_GUNNING_FOG_CUSTOM_COLUMN, '')
        self.gunning_fog_column_combo = CustomColumnComboBox(self, avail_columns, gunning_fog_col)
        gunning_fog_column_label.setBuddy(self.gunning_fog_column_combo)
        readability_layout.addWidget(gunning_fog_column_label, 3, 0, 1, 1)
        readability_layout.addWidget(self.gunning_fog_column_combo, 3, 1, 1, 2)

        # --- Other options ---
        layout.addSpacing(5)
        other_group_box = QGroupBox('Other options:', self)
        layout.addWidget(other_group_box)
        other_group_box_layout = QGridLayout()
        other_group_box.setLayout(other_group_box_layout)

        button_default_label = QLabel('&Button default:', self)
        button_default_label.setToolTip('If plugin is placed as a toolbar button, choose a default action when clicked on')
        self.button_default_combo = KeyValueComboBox(self, BUTTON_DEFAULTS, button_default)
        button_default_label.setBuddy(self.button_default_combo)
        other_group_box_layout.addWidget(button_default_label, 0, 0, 1, 1)
        other_group_box_layout.addWidget(self.button_default_combo, 0, 1, 1, 2)

        self.overwrite_checkbox = QCheckBox('Always overwrite an existing word/page count', self)
        self.overwrite_checkbox.setToolTip('Uncheck this option if you have manually populated values in\n'
                                           'either of your page/word custom columns, and never want the\n'
                                           'plugin to overwrite it. Acts as a convenience option for users\n'
                                           'who have the toolbar button configured to populate both page\n'
                                           'and word count, but for some books have already assigned values\n'
                                           'into a column and just want the zero/blank column populated.')
        self.overwrite_checkbox.setChecked(overwrite_existing)
        other_group_box_layout.addWidget(self.overwrite_checkbox, 1, 0, 1, 3)

        keyboard_shortcuts_button = QPushButton('Keyboard shortcuts...', self)
        keyboard_shortcuts_button.setToolTip(_(
                    'Edit the keyboard shortcuts associated with this plugin'))
        keyboard_shortcuts_button.clicked.connect(self.edit_shortcuts)
        view_prefs_button = QPushButton('&View library preferences...', self)
        view_prefs_button.setToolTip(_(
                    'View data stored in the library database for this plugin'))
        view_prefs_button.clicked.connect(self.view_prefs)
        layout.addWidget(keyboard_shortcuts_button)
        layout.addWidget(view_prefs_button)
        layout.addStretch(1)
Example #10
0
    def settings_dialog(self, window):
        handler = window.wallet.handler
        client = self.client(window.wallet)

        def rename():
            title = _("Set Device Label")
            msg = _("Enter new label:")
            response = QInputDialog().getText(dialog, title, msg)
            if not response[1]:
                return
            new_label = str(response[0])
            client.change_label(new_label)
            device_label.setText(new_label)

        def update_pin_info():
            features = client.features
            pin_label.setText(noyes[features.pin_protection])
            pin_button.setText(_("Change") if features.pin_protection
                               else _("Set"))
            clear_pin_button.setVisible(features.pin_protection)

        def set_pin(remove):
            client.set_pin(remove=remove)
            update_pin_info()

        features = client.features
        noyes = [_("No"), _("Yes")]
        bl_hash = features.bootloader_hash.encode('hex').upper()
        bl_hash = "%s...%s" % (bl_hash[:10], bl_hash[-10:])
        info_tab = QWidget()
        layout = QGridLayout(info_tab)
        device_label = QLabel(features.label)
        rename_button = QPushButton(_("Rename"))
        rename_button.clicked.connect(rename)
        pin_label = QLabel()
        pin_button = QPushButton()
        pin_button.clicked.connect(partial(set_pin, False))
        clear_pin_button = QPushButton(_("Clear"))
        clear_pin_button.clicked.connect(partial(set_pin, True))
        update_pin_info()

        version = "%d.%d.%d" % (features.major_version,
                                features.minor_version,
                                features.patch_version)
        rows = [
            (_("Bootloader Hash"), bl_hash),
            (_("Device ID"), features.device_id),
            (_("Device Label"), device_label, rename_button),
            (_("Firmware Version"), version),
            (_("Language"), features.language),
            (_("Has Passphrase"), noyes[features.passphrase_protection]),
            (_("Has PIN"), pin_label, pin_button, clear_pin_button)
        ]

        for row_num, items in enumerate(rows):
            for col_num, item in enumerate(items):
                widget = item if isinstance(item, QWidget) else QLabel(item)
                layout.addWidget(widget, row_num, col_num)

        dialog = WindowModalDialog(window, _("%s Settings") % self.device)
        vbox = QVBoxLayout()
        tabs = QTabWidget()
        tabs.addTab(info_tab, _("Information"))
        tabs.addTab(QWidget(), _("Advanced"))
        vbox.addWidget(tabs)
        vbox.addStretch(1)
        vbox.addLayout(Buttons(CloseButton(dialog)))

        dialog.setLayout(vbox)
        handler.exec_dialog(dialog)
Example #11
0
        def settings_dialog(self, window):
            def get_client(lookup=DeviceMgr.PAIRED):
                return self.get_client(wallet, lookup)

            def add_rows_to_layout(layout, rows):
                for row_num, items in enumerate(rows):
                    for col_num, txt in enumerate(items):
                        widget = txt if isinstance(txt, QWidget) else QLabel(txt)
                        layout.addWidget(widget, row_num, col_num)

            def refresh():
                features = get_client(DeviceMgr.PAIRED).features
                bl_hash = features.bootloader_hash.encode("hex").upper()
                bl_hash = "%s...%s" % (bl_hash[:10], bl_hash[-10:])
                version = "%d.%d.%d" % (features.major_version, features.minor_version, features.patch_version)
                coins = ", ".join(coin.coin_name for coin in features.coins)

                bl_hash_label.setText(bl_hash)
                device_label.setText(features.label)
                device_id_label.setText(features.device_id)
                initialized_label.setText(noyes[features.initialized])
                version_label.setText(version)
                coins_label.setText(coins)
                pin_label.setText(noyes[features.pin_protection])
                passphrase_label.setText(noyes[features.passphrase_protection])
                language_label.setText(features.language)

                pin_button.setText(_("Change") if features.pin_protection else _("Set"))
                clear_pin_button.setVisible(features.pin_protection)

            def rename():
                title = _("Set Device Label")
                msg = _("Enter new label:")
                response = QInputDialog().getText(dialog, title, msg)
                if not response[1]:
                    return
                get_client().change_label(str(response[0]))
                refresh()

            def toggle_passphrase():
                title = _("Confirm Toggle Passphrase Protection")
                msg = (
                    _(
                        "This will cause your Electrum wallet to be unpaired "
                        "unless your passphrase was or will be empty.\n\n"
                        "This is because addresses will no "
                        "longer correspond to those used by your %s.\n\n"
                        "If your passphrase is not or was not empty you will "
                        "need to create a new Electrum wallet with the install "
                        "wizard so that they match.\n\n"
                        "Are you sure you want to proceed?"
                    )
                    % device
                )
                if not dialog.question(msg, title=title):
                    return
                get_client().toggle_passphrase()
                self.device_manager().close_wallet(wallet)  # Unpair
                refresh()

            def set_pin():
                get_client().set_pin(remove=False)
                refresh()

            def clear_pin():
                title = _("Confirm Clear PIN")
                msg = (
                    _(
                        "WARNING: if your clear your PIN, anyone with physical "
                        "access to your %s device can spend your bitcoins.\n\n"
                        "Are you certain you want to remove your PIN?"
                    )
                    % device
                )
                if not dialog.question(msg, title=title):
                    return
                get_client().set_pin(remove=True)
                refresh()

            def wipe_device():
                # FIXME: cannot yet wipe a device that is only plugged in
                title = _("Confirm Device Wipe")
                msg = _(
                    "Are you sure you want to wipe the device?  "
                    "You should make sure you have a copy of your recovery "
                    "seed and that your wallet holds no bitcoins."
                )
                if not dialog.question(msg, title=title):
                    return
                if sum(wallet.get_balance()):
                    title = _("Confirm Device Wipe")
                    msg = _("Are you SURE you want to wipe the device?\n" "Your wallet still has bitcoins in it!")
                    if not dialog.question(msg, title=title, icon=QMessageBox.Critical):
                        return
                # Note: we use PRESENT so that a user who has forgotten
                # their PIN is not prevented from wiping their device
                get_client(DeviceMgr.PRESENT).wipe_device()
                wallet.wiped()
                self.device_manager().close_wallet(wallet)
                refresh()

            def slider_moved():
                mins = timeout_slider.sliderPosition()
                timeout_label.setText(_("%2d minutes") % mins)

            wallet = window.wallet
            handler = wallet.handler
            device = self.device

            info_tab = QWidget()
            tab_layout = QVBoxLayout(info_tab)
            info_layout = QGridLayout()
            noyes = [_("No"), _("Yes")]
            bl_hash_label = QLabel()
            coins_label = QLabel()
            coins_label.setWordWrap(True)
            device_label = QLabel()
            passphrase_label = QLabel()
            initialized_label = QLabel()
            device_id_label = QLabel()
            version_label = QLabel()
            pin_label = QLabel()
            language_label = QLabel()
            rename_button = QPushButton(_("Rename"))
            rename_button.clicked.connect(rename)
            toggle_passphrase_button = QPushButton(_("Toggle"))
            toggle_passphrase_button.clicked.connect(toggle_passphrase)
            pin_button = QPushButton()
            pin_button.clicked.connect(set_pin)
            clear_pin_button = QPushButton(_("Clear"))
            clear_pin_button.clicked.connect(clear_pin)

            add_rows_to_layout(
                info_layout,
                [
                    (_("Device Label"), device_label, rename_button),
                    (_("Has Passphrase"), passphrase_label, toggle_passphrase_button),
                    (_("Has PIN"), pin_label, pin_button, clear_pin_button),
                    (_("Initialized"), initialized_label),
                    (_("Device ID"), device_id_label),
                    (_("Bootloader Hash"), bl_hash_label),
                    (_("Firmware Version"), version_label),
                    (_("Supported Coins"), coins_label),
                    (_("Language"), language_label),
                ],
            )

            timeout_layout = QHBoxLayout()
            timeout_label = QLabel()
            timeout_slider = QSlider(Qt.Horizontal)
            timeout_slider.setRange(1, 60)
            timeout_slider.setSingleStep(1)
            timeout_slider.setSliderPosition(wallet.session_timeout // 60)
            timeout_slider.setTickInterval(5)
            timeout_slider.setTickPosition(QSlider.TicksBelow)
            timeout_slider.setTracking(True)
            timeout_slider.valueChanged.connect(slider_moved)
            timeout_layout.addWidget(QLabel(_("Session Timeout")))
            timeout_layout.addWidget(timeout_slider)
            timeout_layout.addWidget(timeout_label)

            advanced_tab = QWidget()
            advanced_layout = QGridLayout(advanced_tab)
            wipe_device_button = QPushButton(_("Wipe Device"))
            wipe_device_button.clicked.connect(wipe_device)
            add_rows_to_layout(advanced_layout, [(wipe_device_button,)])

            dialog = WindowModalDialog(window, _("%s Settings") % device)
            vbox = QVBoxLayout()
            tabs = QTabWidget()
            tabs.addTab(info_tab, _("Information"))
            tabs.addTab(advanced_tab, _("Advanced"))
            vbox.addWidget(tabs)
            vbox.addStretch(1)

            # Show values
            slider_moved()
            refresh()

            # QT on MacOSX is sensitive to layout ordering so these are last
            tab_layout.addLayout(info_layout)
            tab_layout.addLayout(timeout_layout)
            vbox.addLayout(Buttons(CloseButton(dialog)))
            dialog.setLayout(vbox)

            handler.exec_dialog(dialog)
            wallet.set_session_timeout(timeout_slider.sliderPosition() * 60)
Example #12
0
    def setup_ui(self):
        set_no_activate_on_click = plugins['progress_indicator'][0].set_no_activate_on_click
        self.setWindowIcon(QIcon(I('spell-check.png')))
        self.l = l = QVBoxLayout(self)
        self.setLayout(l)
        self.stack = s = QStackedLayout()
        l.addLayout(s)
        l.addWidget(self.bb)
        self.bb.clear()
        self.bb.addButton(self.bb.Close)
        b = self.bb.addButton(_('&Refresh'), self.bb.ActionRole)
        b.setToolTip('<p>' + _('Re-scan the book for words, useful if you have edited the book since opening this dialog'))
        b.setIcon(QIcon(I('view-refresh.png')))
        b.clicked.connect(self.refresh)

        self.progress = p = QWidget(self)
        s.addWidget(p)
        p.l = l = QVBoxLayout(p)
        l.setAlignment(Qt.AlignCenter)
        self.progress_indicator = pi = ProgressIndicator(self, 256)
        l.addWidget(pi, alignment=Qt.AlignHCenter), l.addSpacing(10)
        p.la = la = QLabel(_('Checking, please wait...'))
        la.setStyleSheet('QLabel { font-size: 30pt; font-weight: bold }')
        l.addWidget(la, alignment=Qt.AlignHCenter)

        self.main = m = QWidget(self)
        s.addWidget(m)
        m.l = l = QVBoxLayout(m)
        m.h1 = h = QHBoxLayout()
        l.addLayout(h)
        self.filter_text = t = QLineEdit(self)
        t.setPlaceholderText(_('Filter the list of words'))
        t.textChanged.connect(self.do_filter)
        m.fc = b = QToolButton(m)
        b.setIcon(QIcon(I('clear_left.png'))), b.setToolTip(_('Clear filter'))
        b.clicked.connect(t.clear)
        h.addWidget(t), h.addWidget(b)

        m.h2 = h = QHBoxLayout()
        l.addLayout(h)
        self.words_view = w = WordsView(m)
        set_no_activate_on_click(w)
        w.ignore_all.connect(self.ignore_all)
        w.add_all.connect(self.add_all)
        w.activated.connect(self.word_activated)
        w.change_to.connect(self.change_to)
        w.currentChanged = self.current_word_changed
        state = tprefs.get('spell-check-table-state', None)
        hh = self.words_view.horizontalHeader()
        h.addWidget(w)
        self.words_model = m = WordsModel(self)
        w.setModel(m)
        m.dataChanged.connect(self.current_word_changed)
        m.modelReset.connect(self.current_word_changed)
        if state is not None:
            hh.restoreState(state)
            # Sort by the restored state, if any
            w.sortByColumn(hh.sortIndicatorSection(), hh.sortIndicatorOrder())
            m.show_only_misspelt = hh.isSectionHidden(3)

        self.ignore_button = b = QPushButton(_('&Ignore'))
        b.ign_text, b.unign_text = unicode(b.text()), _('Un&ignore')
        b.ign_tt = _('Ignore the current word for the rest of this session')
        b.unign_tt = _('Stop ignoring the current word')
        b.clicked.connect(self.toggle_ignore)
        l = QVBoxLayout()
        h.addLayout(l)
        h.setStretch(0, 1)
        l.addWidget(b), l.addSpacing(20)
        self.add_button = b = QPushButton(_('Add word to &dictionary:'))
        b.add_text, b.remove_text = unicode(b.text()), _('Remove from &dictionaries')
        b.add_tt = _('Add the current word to the specified user dictionary')
        b.remove_tt = _('Remove the current word from all active user dictionaries')
        b.clicked.connect(self.add_remove)
        self.user_dictionaries = d = QComboBox(self)
        self.user_dictionaries_missing_label = la = QLabel(_(
            'You have no active user dictionaries. You must'
            ' choose at least one active user dictionary via'
            ' Preferences->Editor->Manage spelling dictionaries'))
        la.setWordWrap(True)
        self.initialize_user_dictionaries()
        d.setMinimumContentsLength(25)
        l.addWidget(b), l.addWidget(d), l.addWidget(la)
        self.next_occurrence = b = QPushButton(_('Show &next occurrence'), self)
        b.setToolTip('<p>' + _(
            'Show the next occurrence of the selected word in the editor, so you can edit it manually'))
        b.clicked.connect(self.show_next_occurrence)
        l.addSpacing(20), l.addWidget(b)
        l.addStretch(1)

        self.change_button = b = QPushButton(_('&Change selected word to:'), self)
        b.clicked.connect(self.change_word)
        l.addWidget(b)
        self.suggested_word = sw = LineEdit(self)
        sw.set_separator(None)
        sw.setPlaceholderText(_('The replacement word'))
        sw.returnPressed.connect(self.change_word)
        l.addWidget(sw)
        self.suggested_list = sl = QListWidget(self)
        sl.currentItemChanged.connect(self.current_suggestion_changed)
        sl.itemActivated.connect(self.change_word)
        set_no_activate_on_click(sl)
        l.addWidget(sl)

        hh.setSectionHidden(3, m.show_only_misspelt)
        self.show_only_misspelled = om = QCheckBox(_('Show &only misspelled words'))
        om.setChecked(m.show_only_misspelt)
        om.stateChanged.connect(self.update_show_only_misspelt)
        self.case_sensitive_sort = cs = QCheckBox(_('Case &sensitive sort'))
        cs.setChecked(tprefs['spell_check_case_sensitive_sort'])
        cs.stateChanged.connect(self.sort_type_changed)
        self.hb = h = QHBoxLayout()
        self.summary = s = QLabel('')
        self.main.l.addLayout(h), h.addWidget(s), h.addWidget(om), h.addWidget(cs), h.addStretch(1)
Example #13
0
    def settings_dialog(self, window):

        def client():
            return self.client(wallet)

        def add_rows_to_layout(layout, rows):
            for row_num, items in enumerate(rows):
                for col_num, txt in enumerate(items):
                    widget = txt if isinstance(txt, QWidget) else QLabel(txt)
                    layout.addWidget(widget, row_num, col_num)

        def refresh():
            features = client().features
            bl_hash = features.bootloader_hash.encode('hex').upper()
            bl_hash = "%s...%s" % (bl_hash[:10], bl_hash[-10:])
            version = "%d.%d.%d" % (features.major_version,
                                    features.minor_version,
                                    features.patch_version)

            bl_hash_label.setText(bl_hash)
            device_label.setText(features.label)
            device_id_label.setText(features.device_id)
            initialized_label.setText(noyes[features.initialized])
            version_label.setText(version)
            pin_label.setText(noyes[features.pin_protection])
            passphrase_label.setText(noyes[features.passphrase_protection])
            language_label.setText(features.language)

            pin_button.setText(_("Change") if features.pin_protection
                               else _("Set"))
            clear_pin_button.setVisible(features.pin_protection)

        def rename():
            title = _("Set Device Label")
            msg = _("Enter new label:")
            response = QInputDialog().getText(dialog, title, msg)
            if not response[1]:
                return
            client().change_label(str(response[0]))
            refresh()

        def set_pin():
            client().set_pin(remove=False)
            refresh()

        def clear_pin():
            title = _("Confirm Clear PIN")
            msg = _("WARNING: if your clear your PIN, anyone with physical "
                    "access to your %s device can spend your bitcoins.\n\n"
                    "Are you certain you want to remove your PIN?") % device
            if not dialog.question(msg, title=title):
                return
            client().set_pin(remove=True)
            refresh()

        def wipe_device():
            title = _("Confirm Device Wipe")
            msg = _("Are you sure you want to wipe the device?  "
                    "You should make sure you have a copy of your recovery "
                    "seed and that your wallet holds no bitcoins.")
            if not dialog.question(msg, title=title):
                return
            if sum(wallet.get_balance()):
                title = _("Confirm Device Wipe")
                msg = _("Are you SURE you want to wipe the device?\n"
                        "Your wallet still has bitcoins in it!")
                if not dialog.question(msg, title=title,
                                       icon=QMessageBox.Critical):
                    return
            client().wipe_device()
            refresh()

        def slider_moved():
            mins = timeout_slider.sliderPosition()
            timeout_label.setText(_("%2d minutes") % mins)

        wallet = window.wallet
        handler = wallet.handler
        device = self.device

        info_tab = QWidget()
        tab_layout = QVBoxLayout(info_tab)
        info_layout = QGridLayout()
        noyes = [_("No"), _("Yes")]
        bl_hash_label = QLabel()
        device_label = QLabel()
        passphrase_label = QLabel()
        initialized_label = QLabel()
        device_id_label = QLabel()
        version_label = QLabel()
        pin_label = QLabel()
        language_label = QLabel()
        rename_button = QPushButton(_("Rename"))
        rename_button.clicked.connect(rename)
        pin_button = QPushButton()
        pin_button.clicked.connect(set_pin)
        clear_pin_button = QPushButton(_("Clear"))
        clear_pin_button.clicked.connect(clear_pin)

        add_rows_to_layout(info_layout, [
            (_("Device Label"), device_label, rename_button),
            (_("Has Passphrase"), passphrase_label),
            (_("Has PIN"), pin_label, pin_button, clear_pin_button),
            (_("Initialized"), initialized_label),
            (_("Device ID"), device_id_label),
            (_("Bootloader Hash"), bl_hash_label),
            (_("Firmware Version"), version_label),
            (_("Language"), language_label),
        ])
        tab_layout.addLayout(info_layout)

        timeout_layout = QHBoxLayout()
        timeout_label = QLabel()
        timeout_slider = QSlider(Qt.Horizontal)
        timeout_slider.setRange(1, 60)
        timeout_slider.setSingleStep(1)
        timeout_slider.setSliderPosition(wallet.session_timeout // 60)
        timeout_slider.setTickInterval(5)
        timeout_slider.setTickPosition(QSlider.TicksBelow)
        timeout_slider.setTracking(True)
        timeout_slider.valueChanged.connect(slider_moved)
        timeout_layout.addWidget(QLabel(_("Session Timeout")))
        timeout_layout.addWidget(timeout_slider)
        timeout_layout.addWidget(timeout_label)
        tab_layout.addLayout(timeout_layout)

        advanced_tab = QWidget()
        advanced_layout = QGridLayout(advanced_tab)
        wipe_device_button = QPushButton(_("Wipe Device"))
        wipe_device_button.clicked.connect(wipe_device)
        add_rows_to_layout(advanced_layout, [
            (wipe_device_button, ),
        ])

        dialog = WindowModalDialog(window, _("%s Settings") % device)
        vbox = QVBoxLayout()
        tabs = QTabWidget()
        tabs.addTab(info_tab, _("Information"))
        tabs.addTab(advanced_tab, _("Advanced"))
        vbox.addWidget(tabs)
        vbox.addStretch(1)
        vbox.addLayout(Buttons(CloseButton(dialog)))

        # Show values
        slider_moved()
        refresh()
        dialog.setLayout(vbox)
        handler.exec_dialog(dialog)
        wallet.set_session_timeout(timeout_slider.sliderPosition() * 60)