def passphrase_dialog(self, msg, confirm): # If confirm is true, require the user to enter the passphrase twice parent = self.top_level_window() d = WindowModalDialog(parent, _("Enter Passphrase")) if confirm: OK_button = OkButton(d) playout = PasswordLayout(msg=msg, kind=PW_PASSPHRASE, OK_button=OK_button) vbox = QVBoxLayout() vbox.addLayout(playout.layout()) vbox.addLayout(Buttons(CancelButton(d), OK_button)) d.setLayout(vbox) passphrase = playout.new_password() if d.exec_() else None else: pw = QLineEdit() pw.setEchoMode(2) pw.setMinimumWidth(200) vbox = QVBoxLayout() vbox.addWidget(WWLabel(msg)) vbox.addWidget(pw) vbox.addLayout(Buttons(CancelButton(d), OkButton(d))) d.setLayout(vbox) passphrase = pw.text() if d.exec_() else None self.passphrase = passphrase self.done.set()
def __init__(self, parent, title=None): WindowModalDialog.__init__(self, parent, title=title) vbox = QVBoxLayout(self) cron_list = CronPaymentsList(parent) vbox.addWidget(cron_list) vbox.addStretch() vbox.addLayout(Buttons(QPushButton('Edit'), QPushButton('Delete'), )) vbox.addStretch() vbox.addLayout(Buttons(CloseButton(self), ))
def __init__(self, parent): super(MatrixDialog, self).__init__(parent) self.setWindowTitle(_("Trezor Matrix Recovery")) self.num = 9 self.loop = QEventLoop() vbox = QVBoxLayout(self) vbox.addWidget(WWLabel(MATRIX_RECOVERY)) grid = QGridLayout() grid.setSpacing(0) self.char_buttons = [] for y in range(3): for x in range(3): button = QPushButton('?') button.clicked.connect( partial(self.process_key, ord('1') + y * 3 + x)) grid.addWidget(button, 3 - y, x) self.char_buttons.append(button) vbox.addLayout(grid) self.backspace_button = QPushButton("<=") self.backspace_button.clicked.connect( partial(self.process_key, Qt.Key_Backspace)) self.cancel_button = QPushButton(_("Cancel")) self.cancel_button.clicked.connect( partial(self.process_key, Qt.Key_Escape)) buttons = Buttons(self.backspace_button, self.cancel_button) vbox.addSpacing(40) vbox.addLayout(buttons) self.refresh() self.show()
def __init__(self, parent): super(CharacterDialog, self).__init__(parent) self.setWindowTitle(_("KeepKey Seed Recovery")) self.character_pos = 0 self.word_pos = 0 self.loop = QEventLoop() self.word_help = QLabel() self.char_buttons = [] vbox = QVBoxLayout(self) vbox.addWidget(WWLabel(CHARACTER_RECOVERY)) hbox = QHBoxLayout() hbox.addWidget(self.word_help) for i in range(4): char_button = CharacterButton('*') char_button.setMaximumWidth(36) self.char_buttons.append(char_button) hbox.addWidget(char_button) self.accept_button = CharacterButton(_("Accept Word")) self.accept_button.clicked.connect(partial(self.process_key, 32)) self.rejected.connect(partial(self.loop.exit, 1)) hbox.addWidget(self.accept_button) hbox.addStretch(1) vbox.addLayout(hbox) self.finished_button = QPushButton(_("Seed Entered")) self.cancel_button = QPushButton(_("Cancel")) self.finished_button.clicked.connect( partial(self.process_key, Qt.Key_Return)) self.cancel_button.clicked.connect(self.rejected) buttons = Buttons(self.finished_button, self.cancel_button) vbox.addSpacing(40) vbox.addLayout(buttons) self.refresh() self.show()
def settings_dialog(self, window): # Return a settings dialog. d = WindowModalDialog(window, _("Bitpost settings")) vbox = QVBoxLayout(d) d.setMinimumSize(500, 200) vbox.addStretch() vbox.addLayout(Buttons(CloseButton(d), OkButton(d))) d.show()
def cypherseed_dialog(self, window): self.warn_old_revealer() d = WindowModalDialog(window, "Encryption Dialog") d.setMinimumWidth(500) d.setMinimumHeight(210) d.setMaximumHeight(450) d.setContentsMargins(11, 11, 1, 1) self.c_dialog = d hbox = QHBoxLayout(d) self.vbox = QVBoxLayout() logo = QLabel() hbox.addWidget(logo) logo.setPixmap(QPixmap(icon_path('revealer.png'))) logo.setAlignment(Qt.AlignLeft) hbox.addSpacing(16) self.vbox.addWidget( WWLabel("<b>" + _("Revealer Secret Backup Plugin") + "</b><br>" + _("Ready to encrypt for revealer {}").format( self.versioned_seed.version + '_' + self.versioned_seed.checksum))) self.vbox.addSpacing(11) hbox.addLayout(self.vbox) grid = QGridLayout() self.vbox.addLayout(grid) cprint = QPushButton(_("Encrypt {}'s seed").format(self.wallet_name)) cprint.setMaximumWidth(250) cprint.clicked.connect(partial(self.seed_img, True)) self.vbox.addWidget(cprint) self.vbox.addSpacing(1) self.vbox.addWidget( WWLabel("<b>" + _("OR") + "</b> " + _("type a custom alphanumerical secret below:"))) self.text = ScanQRTextEdit() self.text.setTabChangesFocus(True) self.text.setMaximumHeight(70) self.text.textChanged.connect(self.customtxt_limits) self.vbox.addWidget(self.text) self.char_count = WWLabel("") self.char_count.setAlignment(Qt.AlignRight) self.vbox.addWidget(self.char_count) self.max_chars = WWLabel( "<font color='red'>" + _("This version supports a maximum of {} characters.").format( self.MAX_PLAINTEXT_LEN) + "</font>") self.vbox.addWidget(self.max_chars) self.max_chars.setVisible(False) self.ctext = QPushButton(_("Encrypt custom secret")) self.ctext.clicked.connect(self.t) self.vbox.addWidget(self.ctext) self.ctext.setEnabled(False) self.vbox.addSpacing(11) self.vbox.addLayout(Buttons(CloseButton(d))) return bool(d.exec_())
def show_settings_dialog(self, window, success): if not success: window.show_message(_('Server not reachable.')) return wallet = window.wallet d = WindowModalDialog(window, _("TrustedCoin Information")) d.setMinimumSize(500, 200) vbox = QVBoxLayout(d) hbox = QHBoxLayout() logo = QLabel() logo.setPixmap(QPixmap(icon_path("tc.jpeg"))) msg = _('This wallet is protected by TrustedCoin\'s two-factor authentication.') + '<br/>' \ + _( "For more information, visit") + " <a href=\"https://api.trustedcoin.com/#/electrum-help\">https://api.trustedcoin.com/#/electrum-help</a>" label = QLabel(msg) label.setOpenExternalLinks(1) hbox.addStretch(10) hbox.addWidget(logo) hbox.addStretch(10) hbox.addWidget(label) hbox.addStretch(10) vbox.addLayout(hbox) vbox.addStretch(10) msg = _( 'TrustedCoin charges a small fee to co-sign transactions. The fee depends on how many prepaid transactions you buy. An extra output is added to your transaction every time you run out of prepaid transactions.') + '<br/>' label = QLabel(msg) label.setWordWrap(1) vbox.addWidget(label) vbox.addStretch(10) grid = QGridLayout() vbox.addLayout(grid) price_per_tx = wallet.price_per_tx n_prepay = wallet.num_prepay(self.config) i = 0 for k, v in sorted(price_per_tx.items()): if k == 1: continue grid.addWidget(QLabel("Pay every %d transactions:" % k), i, 0) grid.addWidget(QLabel(window.format_amount(v / k) + ' ' + window.base_unit() + "/tx"), i, 1) b = QRadioButton() b.setChecked(k == n_prepay) b.clicked.connect(lambda b, k=k: self.config.set_key('trustedcoin_prepay', k, True)) grid.addWidget(b, i, 2) i += 1 n = wallet.billing_info.get('tx_remaining', 0) grid.addWidget(QLabel(_("Your wallet has {} prepaid transactions.").format(n)), i, 0) vbox.addLayout(Buttons(CloseButton(d))) d.exec_()
def setup_dialog(self, window): self.wallet = window.parent().wallet self.update_wallet_name(self.wallet) self.user_input = False self.d = WindowModalDialog(window, "Setup Dialog") self.d.setMinimumWidth(500) self.d.setMinimumHeight(210) self.d.setMaximumHeight(320) self.d.setContentsMargins(11, 11, 1, 1) self.hbox = QHBoxLayout(self.d) vbox = QVBoxLayout() logo = QLabel() self.hbox.addWidget(logo) logo.setPixmap(QPixmap(icon_path('revealer.png'))) logo.setAlignment(Qt.AlignLeft) self.hbox.addSpacing(16) vbox.addWidget( WWLabel("<b>" + _("Revealer Visual Cryptography Plugin") + "</b><br><br>" + _("To encrypt a secret, first create or load noise.") + "<br/>")) vbox.addSpacing(7) bcreate = QPushButton(_("Create a new Revealer")) bcreate.setMaximumWidth(181) bcreate.setDefault(True) vbox.addWidget(bcreate, Qt.AlignCenter) self.load_noise = ScanQRTextEdit(config=self.config) self.load_noise.setTabChangesFocus(True) self.load_noise.textChanged.connect(self.on_edit) self.load_noise.setMaximumHeight(33) self.hbox.addLayout(vbox) vbox.addWidget( WWLabel( _("or type an existing revealer code below and click 'next':")) ) vbox.addWidget(self.load_noise) vbox.addSpacing(3) self.next_button = QPushButton(_("Next"), self.d) self.next_button.setEnabled(False) vbox.addLayout(Buttons(self.next_button)) self.next_button.clicked.connect(self.d.close) self.next_button.clicked.connect( partial(self.cypherseed_dialog, window)) def mk_digital(): try: self.make_digital(self.d) except Exception: self.logger.exception('') else: self.cypherseed_dialog(window) bcreate.clicked.connect(mk_digital) return bool(self.d.exec_())
def settings_dialog(self, window): d = WindowModalDialog(window, _("Email settings")) d.setMinimumSize(500, 200) vbox = QVBoxLayout(d) vbox.addWidget(QLabel(_('Server hosting your email acount'))) grid = QGridLayout() vbox.addLayout(grid) grid.addWidget(QLabel('Server (SMTP)'), 0, 0) server_s = QLineEdit() server_s.setText(self.smtp_server) grid.addWidget(server_s, 0, 1) grid.addWidget(QLabel('Username'), 1, 0) username_e = QLineEdit() username_e.setText(self.username) grid.addWidget(username_e, 1, 1) grid.addWidget(QLabel('Password'), 2, 0) password_e = QLineEdit() password_e.setText(self.password) grid.addWidget(password_e, 2, 1) vbox.addStretch() vbox.addLayout(Buttons(CloseButton(d), OkButton(d))) if not d.exec_(): return smtp_server = str(server_s.text()) self.config.set_key('email_smtp', smtp_server) self.smtp_server = smtp_server username = str(username_e.text()) self.config.set_key('email_username', username) self.username = username password = str(password_e.text()) self.config.set_key('email_password', password) self.password = password self.processor = None if self.smtp_server and self.username and self.password: try: conn = smtplib.SMTP_SSL(self.smtp_server, timeout=5) conn.login(self.username, self.password) self.processor = Processor(self.smtp_server, self.username, self.password, self.on_receive) self.processor.start() except BaseException as e: window.show_message( _("Unable to connect to mail server:\n {}").format(e) + "\n" + _("Please check your connection and credentials.") )
def message_dialog(self, msg, on_cancel): # Called more than once during signing, to confirm output and fee self.clear_dialog() title = _('Please check your {} device').format(self.device) self.dialog = dialog = WindowModalDialog(self.top_level_window(), title) l = QLabel(msg) vbox = QVBoxLayout(dialog) vbox.addWidget(l) if on_cancel: dialog.rejected.connect(on_cancel) vbox.addLayout(Buttons(CancelButton(dialog))) dialog.show()
def pin_dialog(self, msg, show_strength): # Needed e.g. when resetting a device self.clear_dialog() dialog = WindowModalDialog(self.top_level_window(), _("Enter PIN")) matrix = self.pin_matrix_widget_class(show_strength) vbox = QVBoxLayout() vbox.addWidget(QLabel(msg)) vbox.addWidget(matrix) vbox.addLayout(Buttons(CancelButton(dialog), OkButton(dialog))) dialog.setLayout(vbox) dialog.exec_() self.response = str(matrix.get_value()) self.done.set()
def pin_dialog(self, msg): # Needed e.g. when resetting a device from trezorlib.qt.pinmatrix import PinMatrixWidget self.clear_dialog() dialog = WindowModalDialog(self.top_level_window(), _("Enter PIN")) matrix = PinMatrixWidget() vbox = QVBoxLayout() vbox.addWidget(QLabel(msg)) vbox.addWidget(matrix) vbox.addLayout(Buttons(CancelButton(dialog), OkButton(dialog))) dialog.setLayout(vbox) dialog.exec_() self.response = str(matrix.get_value()) self.done.set()
def settings_dialog(self, window): d = WindowModalDialog(window, _("Email settings")) d.setMinimumSize(500, 200) vbox = QVBoxLayout(d) vbox.addWidget(QLabel(_('Server hosting your email account'))) grid = QGridLayout() vbox.addLayout(grid) grid.addWidget(QLabel('Server (IMAP)'), 0, 0) server_e = QLineEdit() server_e.setText(self.imap_server) grid.addWidget(server_e, 0, 1) grid.addWidget(QLabel('Username'), 1, 0) username_e = QLineEdit() username_e.setText(self.username) grid.addWidget(username_e, 1, 1) grid.addWidget(QLabel('Password'), 2, 0) password_e = QLineEdit() password_e.setText(self.password) grid.addWidget(password_e, 2, 1) vbox.addStretch() vbox.addLayout(Buttons(CloseButton(d), OkButton(d))) if not d.exec_(): return server = str(server_e.text()) self.config.set_key('email_server', server) self.imap_server = server username = str(username_e.text()) self.config.set_key('email_username', username) self.username = username password = str(password_e.text()) self.config.set_key('email_password', password) self.password = password check_connection = CheckConnectionThread(server, username, password) check_connection.connection_error_signal.connect( lambda e: window.show_message( _("Unable to connect to mail server:\n {error}").format( error=e) + "\n" + _( "Please check your connection and credentials."))) check_connection.start()
def _add_advanced_button(self): self._translate_advanced_options() self.advanced_button = QPushButton(self._SHOW_ADVANCED_TEXT) self.advanced_button.clicked.connect(self._toggle_button) layout = self.layout() for i in range(layout.count()): item = layout.itemAt(i) if isinstance(item, Buttons): layout.removeItem(item) break layout.addLayout(Buttons( self.advanced_button, self.back_button, self.next_button, )) self.advanced_button.setVisible(False)
def wallet_info_buttons(self, main_window, dialog): # user is about to see the "Wallet Information" dialog # - add a button if multisig wallet, and a Coldcard is a cosigner. wallet = main_window.wallet if type(wallet) is not Multisig_Wallet: return if not any(type(ks) == self.keystore_class for ks in wallet.get_keystores()): # doesn't involve a Coldcard wallet, hide feature return btn = QPushButton(_("Export for Coldcard")) btn.clicked.connect(lambda unused: self.export_multisig_setup(main_window, wallet)) return Buttons(btn, CloseButton(dialog))
def calibration_dialog(self, window): d = WindowModalDialog(window, _("Revealer - Printer calibration settings")) d.setMinimumSize(100, 200) vbox = QVBoxLayout(d) vbox.addWidget( QLabel(''.join([ "<br/>", _("If you have an old printer, or want optimal precision"), "<br/>", _("print the calibration pdf and follow the instructions "), "<br/>", "<br/>", ]))) self.calibration_h = self.config.get('calibration_h') self.calibration_v = self.config.get('calibration_v') cprint = QPushButton(_("Open calibration pdf")) cprint.clicked.connect(self.calibration) vbox.addWidget(cprint) vbox.addWidget(QLabel(_('Calibration values:'))) grid = QGridLayout() vbox.addLayout(grid) grid.addWidget(QLabel(_('Right side')), 0, 0) horizontal = QLineEdit() horizontal.setText(str(self.calibration_h)) grid.addWidget(horizontal, 0, 1) grid.addWidget(QLabel(_('Bottom')), 1, 0) vertical = QLineEdit() vertical.setText(str(self.calibration_v)) grid.addWidget(vertical, 1, 1) vbox.addStretch() vbox.addSpacing(13) vbox.addLayout(Buttons(CloseButton(d), OkButton(d))) if not d.exec_(): return self.calibration_h = int(Decimal(horizontal.text())) self.config.set_key('calibration_h', self.calibration_h) self.calibration_v = int(Decimal(vertical.text())) self.config.set_key('calibration_v', self.calibration_v)
def auth_dialog(self, window): d = WindowModalDialog(window, _("Authorization")) vbox = QVBoxLayout(d) pw = AmountEdit(None, is_int = True) msg = _('Please enter your Google Authenticator code') vbox.addWidget(QLabel(msg)) grid = QGridLayout() grid.setSpacing(8) grid.addWidget(QLabel(_('Code')), 1, 0) grid.addWidget(pw, 1, 1) vbox.addLayout(grid) msg = _('If you have lost your second factor, you need to restore your wallet from seed in order to request a new code.') label = QLabel(msg) label.setWordWrap(1) vbox.addWidget(label) vbox.addLayout(Buttons(CancelButton(d), OkButton(d))) if not d.exec_(): return return pw.get_amount()
def settings_dialog(self, window): wallet = window.parent().wallet d = WindowModalDialog(window, _("Label Settings")) hbox = QHBoxLayout() hbox.addWidget(QLabel("Label sync options:")) upload = ThreadedButton("Force upload", partial(self.push_thread, wallet), partial(self.done_processing, d)) download = ThreadedButton("Force download", partial(self.pull_thread, wallet, True), partial(self.done_processing, d)) vbox = QVBoxLayout() vbox.addWidget(upload) vbox.addWidget(download) hbox.addLayout(vbox) vbox = QVBoxLayout(d) vbox.addLayout(hbox) vbox.addSpacing(20) vbox.addLayout(Buttons(OkButton(d))) return bool(d.exec_())
def __init__(self, *, window: 'ElectrumWindow', txs, password, is_sweep): WindowModalDialog.__init__(self, window, _('BitPost Transactions Preview')) self.setMinimumSize(800, 600) self.main_window = window self.txs = txs self.password_required = self.main_window.wallet.has_keystore_encryption( ) and not is_sweep self.is_send = False vbox = QVBoxLayout() self.setLayout(vbox) lbox = QListWidget() items = [] for tx in txs: inputs = tx.inputs() outputs = tx.outputs() fee = tx.get_fee() fiat = False text = "fee: {}".format(fee) if self.main_window.fx and self.main_window.fx.is_enabled(): fiat = Exchange(self.main_window.fx) text += fiat.str_exchange(fee) text += "\t\tvbyte: {}\n".format(tx.estimated_size()) tmp = "fee/vbyte: {}".format(round(fee / tx.estimated_size(), 2)) if fiat: tmp += fiat.str_exchange(fee / tx.estimated_size()) text += tmp if len(tmp) > 22: tab = "\t" else: tab = "\t\t" text += "{}total size: {}\n".format(tab, tx.estimated_total_size()) text += "INPUTS:\n" for i in inputs: text += "{}:{} = {}".format(i.prevout.txid.hex(), i.prevout.out_idx, i.value_sats()) if fiat: text += fiat.str_exchange(i.value_sats()) text += "\n" text += "OUTPUTS:\n" for o in outputs: text += "{} = {}".format(o.address, o.value) if fiat: text += fiat.str_exchange(o.value) text += "\n" items.append(text) lbox.addItems(items) vbox.addWidget(lbox) self.send_button = QPushButton(_('Send')) self.send_button.clicked.connect(self.on_send) self.send_button.setDefault(True) self.pw_label = QLabel(_('Password')) self.pw_label.setVisible(self.password_required) self.pw = PasswordLineEdit(password) self.pw.setVisible(self.password_required) vbox.addLayout( Buttons(CancelButton(self), self.pw_label, self.pw, self.send_button))
def __init__(self, window, plugin, keystore, device_id): title = _("{} Settings").format(plugin.device) super(SettingsDialog, self).__init__(window, title) self.setMaximumWidth(540) devmgr = plugin.device_manager() config = devmgr.config handler = keystore.handler thread = keystore.thread def invoke_client(method, *args, **kw_args): unpair_after = kw_args.pop('unpair_after', False) def task(): client = devmgr.client_by_id(device_id) 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 = bh2u(features.bootloader_hash) 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', 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 set_pin(): invoke_client('set_pin', remove=False) def clear_pin(): invoke_client('set_pin', remove=True) def wipe_device(): wallet = window.wallet 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 bitgesells 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").format(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 {}. If you have multiple devices " "their labels help distinguish them.").format(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 bitgesells if they obtain physical " "access to your {}.").format(plugin.device)) pin_msg.setWordWrap(True) pin_msg.setStyleSheet("color: red") settings_glayout.addWidget(pin_msg, 3, 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 " "{} device can spend your bitgesells.").format(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 bitgesells " "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)
def settings_dialog(self, window): # hack to workaround a bug: https://github.com/spesmilo/electrum/commit/4d8fcded4b42fd673bbb61f85aa99dc329be28a4 if self.closed: # if this plugin instance is supposed to be closed and we have a different newer instance available, # forward the call to the newer one. if self.parent.bwt and self.parent.bwt != self: self.parent.bwt.settings_dialog(window) return if not self.wallets: window.show_error(_('No hd wallets found.')) return d = WindowModalDialog(window, _('Connect to Bitcoin Core with bwt')) d.setMinimumWidth(570) vbox = QVBoxLayout(d) form = QFormLayout() form.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter) vbox.addLayout(form) form.addRow(title(_('Bitcoin Core settings'))) url_e = input(self.bitcoind_url) form.addRow(_('RPC URL:'), url_e) cred_e = input(self.bitcoind_cred) cred_e.setPlaceholderText('<username>:<password>') form.addRow(_('RPC Auth:'), cred_e) form.addRow('', helptext(_('Leave blank to use the cookie.'), False)) dir_e = input(self.bitcoind_dir) form.addRow(_('Directory:'), dir_e) form.addRow('', helptext(_('Used for reading the cookie file. Ignored if auth is set.'), False)) wallet_e = input(self.bitcoind_wallet, 150) form.addRow(_('Wallet:'), wallet_e) form.addRow('', helptext(_('For use with multi-wallet. Leave blank to use the default wallet.'), False)) form.addRow(title(_('Other settings'))) rescan_c = QComboBox() rescan_c.addItems([ _('All history'), _('Since date'), _('None') ]) rescan_c.setMaximumWidth(150) rescan_e = input(None, 150) rescan_e.setPlaceholderText('yyyy-mm-dd') apply_rescan(self.rescan_since, rescan_c, rescan_e) rescan_c.currentIndexChanged.connect(lambda i: rescan_e.setVisible(i == 1)) rescan_l = QHBoxLayout() rescan_l.addWidget(rescan_c) rescan_l.addWidget(rescan_e) form.addRow(_('Scan:'), rescan_l) form.addRow('', helptext(_('Set to the wallet creation date to reduce scanning time.'), False)) custom_opt_e = input(self.custom_opt) custom_opt_e.setPlaceholderText('e.g. --gap-limit 50 --poll-interval 1') form.addRow('Options', custom_opt_e) form.addRow('', helptext(_('Additional custom options. Optional.'), False)) verbose_c = QComboBox() verbose_c.addItems([ _('info'), _('debug'), _('trace') ]) verbose_c.setCurrentIndex(self.verbose) verbose_c.setMaximumWidth(150) form.addRow('Log level:', verbose_c) log_t = QTextEdit() log_t.setReadOnly(True) log_t.setFixedHeight(80) log_t.setStyleSheet('QTextEdit { color: #888; font-size: 0.9em }') log_t.setWordWrapMode(QTextOption.WrapAnywhere) sp = log_t.sizePolicy() sp.setRetainSizeWhenHidden(True) log_t.setSizePolicy(sp) log_t.hide() form.addRow(log_t) self.log_signal.connect(partial(show_log, log_t)) def save_config_and_run(): self.enabled = True self.bitcoind_url = str(url_e.text()) self.bitcoind_dir = str(dir_e.text()) self.bitcoind_cred = str(cred_e.text()) self.bitcoind_wallet = str(wallet_e.text()) self.rescan_since = get_rescan_value(rescan_c, rescan_e) self.custom_opt = str(custom_opt_e.text()) self.verbose = verbose_c.currentIndex() self.config.set_key('bwt_enabled', self.enabled) self.config.set_key('bwt_bitcoind_url', self.bitcoind_url) self.config.set_key('bwt_bitcoind_dir', self.bitcoind_dir) self.config.set_key('bwt_bitcoind_cred', self.bitcoind_cred) self.config.set_key('bwt_bitcoind_wallet', self.bitcoind_wallet) self.config.set_key('bwt_rescan_since', self.rescan_since) self.config.set_key('bwt_custom_opt', self.custom_opt) self.config.set_key('bwt_verbose', self.verbose) log_t.clear() log_t.show() self.start() window.show_message(_('bwt is starting, check the logs for additional information. The bwt server will be available after Bitcoin Core completes rescanning, which may take awhile.')) log_t.ensureCursorVisible() save_b = QPushButton('Save && Connect') save_b.setDefault(True) save_b.clicked.connect(save_config_and_run) vbox.addLayout(Buttons(CloseButton(d), save_b)) d.exec_() self.log_signal.disconnect()
def setup_dialog(self, window): self.wallet = window.parent().wallet self.update_wallet_name(self.wallet) self.user_input = False self.d = WindowModalDialog(window, "Setup Dialog") self.d.setMinimumWidth(500) self.d.setMinimumHeight(210) self.d.setMaximumHeight(320) self.d.setContentsMargins(11, 11, 1, 1) self.hbox = QHBoxLayout(self.d) vbox = QVBoxLayout() logo = QLabel() self.hbox.addWidget(logo) logo.setPixmap(QPixmap(icon_path('revealer.png'))) logo.setAlignment(Qt.AlignLeft) self.hbox.addSpacing(16) vbox.addWidget( WWLabel( "<b>" + _("Revealer Secret Backup Plugin") + "</b><br>" + _("To encrypt your backup, first we need to load some noise.") + "<br/>")) vbox.addSpacing(7) bcreate = QPushButton(_("Create a new Revealer")) bcreate.setMaximumWidth(181) bcreate.setDefault(True) vbox.addWidget(bcreate, Qt.AlignCenter) self.load_noise = ScanQRTextEdit() self.load_noise.setTabChangesFocus(True) self.load_noise.textChanged.connect(self.on_edit) self.load_noise.setMaximumHeight(33) self.hbox.addLayout(vbox) vbox.addWidget( WWLabel( _("or type an existing revealer code below and click 'next':")) ) vbox.addWidget(self.load_noise) vbox.addSpacing(3) self.next_button = QPushButton(_("Next"), self.d) self.next_button.setEnabled(False) vbox.addLayout(Buttons(self.next_button)) self.next_button.clicked.connect(self.d.close) self.next_button.clicked.connect( partial(self.cypherseed_dialog, window)) vbox.addWidget( QLabel("<b>" + _("Warning") + "</b>: " + _( "Each revealer should be used only once." ) + "<br>" + _( "more information at <a href=\"https://revealer.cc/faq\">https://revealer.cc/faq</a>" ))) def mk_digital(): try: self.make_digital(self.d) except Exception: traceback.print_exc(file=sys.stdout) else: self.cypherseed_dialog(window) bcreate.clicked.connect(mk_digital) return bool(self.d.exec_())
def create_settings_window(small_window): window = get_parent_main_window(small_window) d = WindowModalDialog(window, _("Bitpost settings")) vbox = QVBoxLayout(d) d.setMinimumSize(500, 200) hbox_maxfee = QHBoxLayout() hbox_maxfee.addWidget(QLabel("Default max fee to use")) max_fees_e = QLineEdit() max_fees_e.setText(str(window.config.get('bitpost_max_fee'))) hbox_maxfee.addWidget(max_fees_e) fee_combo = QComboBox() fee_combo_values = get_fee_units(window, window.config.get('bitpost_max_fee_unit')) fee_combo.addItems(fee_combo_values) hbox_maxfee.addWidget(fee_combo) help_button__max_fee = QPushButton("?") help_button__max_fee.clicked.connect( lambda: d.show_message(HelpTexts.max_fee)) hbox_maxfee.addWidget(help_button__max_fee) vbox.addLayout(hbox_maxfee) empty_line = QHBoxLayout() empty_line.addWidget(QLabel("")) vbox.addLayout(empty_line) advanced_settings_title = QHBoxLayout() advanced_settings_title.addStretch() advanced_settings_title.addWidget(QLabel("<b>Notifications</b>")) advanced_settings_title.addStretch() vbox.addLayout(advanced_settings_title) telegram_reminder = QLabel( _("<b>Remember to start <a href='https:/t.me/bitpostbot'>@BitpostBot</a></b>" )) telegram_reminder.setVisible(True if window.config.get( 'bitpost_notification_platform') == 'Telegram' else False) telegram_reminder.setOpenExternalLinks(True) platform_address = QHBoxLayout() platform_address.addWidget(QLabel("Platform")) platform_combo = QComboBox() fee_combo_values = ['None', 'Email', 'Twitter', 'Telegram'] platform_combo.addItems(fee_combo_values) platform_combo.setCurrentText( window.config.get('bitpost_notification_platform')) platform_combo.currentTextChanged.connect( lambda: telegram_reminder.setVisible(True) if platform_combo. currentText() == 'Telegram' else telegram_reminder.setVisible(False)) platform_address.addWidget(platform_combo) platform_address.addWidget(QLabel("Address/handle")) vbox.addLayout(platform_address) address_input = QLineEdit() address_input.setText(window.config.get('bitpost_notification_address', '')) platform_address.addWidget(address_input) vbox.addWidget(telegram_reminder) subscription_title = QHBoxLayout() subscription_title.addWidget(QLabel("Subscriptions")) subscriptions_help = QPushButton("?") subscriptions_help.clicked.connect( lambda: d.show_message(HelpTexts.subscriptions)) subscription_title.addWidget(subscriptions_help) subscription_title.addStretch() vbox.addLayout(subscription_title) subscriptions = { subscription['name'] for subscription in window.config.get( 'bitpost_notification_subscriptions') } subscriptions1 = QVBoxLayout() overdue_checkbox = QCheckBox("Overdue") if 'overdue' in subscriptions: overdue_checkbox.setChecked(True) subscriptions1.addWidget(overdue_checkbox) mined_checkbox = QCheckBox("Mined") if 'mine' in subscriptions: mined_checkbox.setChecked(True) subscriptions1.addWidget(mined_checkbox) max_fee_reached_checkbox = QCheckBox("Maximum fee reached") if 'reached' in subscriptions: max_fee_reached_checkbox.setChecked(True) subscriptions1.addWidget(max_fee_reached_checkbox) vbox.addLayout(subscriptions1) reorg_checkbox = QCheckBox("Block reorganization") if 'orphaned_block' in subscriptions: reorg_checkbox.setChecked(True) subscriptions1.addWidget(reorg_checkbox) orphaned_checkbox = QCheckBox("Child transaction orphaned") if '' in subscriptions: orphaned_checkbox.setChecked(True) subscriptions1.addWidget(orphaned_checkbox) advanced_settings_title = QHBoxLayout() advanced_settings_title.addStretch() advanced_settings_title.addWidget(QLabel("<b>Advanced Settings</b>")) advanced_settings_title.addStretch() vbox.addLayout(advanced_settings_title) hbox_ntx = QHBoxLayout() hbox_ntx.addWidget(QLabel("Default number of Txs")) num_txs_e = QLineEdit() num_txs_e.setText(str(window.config.get('bitpost_num_txs'))) hbox_ntx.addWidget(num_txs_e) help_button__num_txs = QPushButton("?") help_button__num_txs.clicked.connect( lambda: d.show_message(HelpTexts.num_txs)) hbox_ntx.addWidget(help_button__num_txs) vbox.addLayout(hbox_ntx) broadcast_policy = QHBoxLayout() broadcast_policy.addWidget(QLabel("First broadcast policy")) broadcast_policy_combo = QComboBox() # 'Broadcast lowest fee transaction immediatly' broadcast_policy_options = [ 'Don\'t delay first broadcast', 'Allow delay of first broadcast' ] if window.config.get('bitpost_delay') == 1: broadcast_policy_options.reverse() broadcast_policy_combo.addItems(broadcast_policy_options) broadcast_policy.addWidget(broadcast_policy_combo) help_button__broadcast_policy = QPushButton("?") help_button__broadcast_policy.clicked.connect( lambda: d.show_message(HelpTexts.delay)) broadcast_policy.addWidget(help_button__broadcast_policy) vbox.addLayout(broadcast_policy) vbox.addStretch() vbox.addLayout(Buttons(CloseButton(d), OkButton(d))) if not d.exec_(): return window.config.set_key('bitpost_max_fee_unit', fee_combo.currentText()) delay = 1 if broadcast_policy_combo.currentText( ) == 'Allow delay of first broadcast' else 0 window.config.set_key('bitpost_delay', delay) platform_text = platform_combo.currentText() window.config.set_key('bitpost_notification_platform', platform_text) subscriptions = [] if overdue_checkbox.isChecked(): subscriptions.append({'name': 'overdue'}) if mined_checkbox.isChecked(): subscriptions.append({'name': 'mine'}) if max_fee_reached_checkbox.isChecked(): subscriptions.append({'name': 'reached'}) if reorg_checkbox.isChecked(): subscriptions.append({'name': 'orphaned_block'}) if orphaned_checkbox.isChecked(): pass # TODO window.config.set_key('bitpost_notification_subscriptions', subscriptions) try: window.config.set_key('bitpost_max_fee', float(max_fees_e.text())) except: d.show_error('Invalid maximum fee, must be a number.') create_settings_window(small_window) try: window.config.set_key('bitpost_num_txs', int(num_txs_e.text())) except: d.show_error( 'Invalid default number of transactions, must be an integer') create_settings_window(small_window) if not valid_address(platform_combo.currentText(), address_input.text()): d.show_error('Invalid handle/address for ' + platform_combo.currentText()) create_settings_window(small_window) window.config.set_key('bitpost_notification_address', address_input.text())
def __init__(self, window, plugin, keystore, device_id): title = _("{} Settings").format(plugin.device) super(SettingsDialog, self).__init__(window, title) self.setMaximumWidth(540) devmgr = plugin.device_manager() config = devmgr.config handler = keystore.handler thread = keystore.thread hs_cols, hs_rows = (128, 64) def invoke_client(method, *args, **kw_args): unpair_after = kw_args.pop('unpair_after', False) def task(): client = devmgr.client_by_id(device_id) 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() if features.bootloader_hash: bl_hash = bh2u(features.bootloader_hash) bl_hash = "\n".join([bl_hash[:32], bl_hash[32:]]) else: bl_hash = "N/A" 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) 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) 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', 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-CHI 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-CHI 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(): dialog = QFileDialog(self, _("Choose Homescreen")) filename, __ = dialog.getOpenFileName() if not filename: return # user cancelled if filename.endswith('.toif'): img = open(filename, 'rb').read() if img[:8] != b'TOIf\x90\x00\x90\x00': handler.show_error( 'File is not a TOIF file with size of 144x144') return else: from PIL import Image # FIXME im = Image.open(filename) if im.size != (128, 64): handler.show_error('Image must be 128 x 64 pixels') return im = im.convert('1') pix = im.load() img = bytearray(1024) for j in range(64): for i in range(128): if pix[i, j]: o = (i + j * 128) img[o // 8] |= (1 << (7 - o % 8)) img = bytes(img) invoke_client('change_homescreen', img) def clear_homescreen(): invoke_client('change_homescreen', b'\x00') def set_pin(): invoke_client('set_pin', remove=False) def clear_pin(): invoke_client('set_pin', remove=True) def wipe_device(): wallet = window.wallet 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 CHI 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").format(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) 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), (_("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 {}. If you have multiple devices " "their labels help distinguish them.").format(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 CHI if they obtain physical " "access to your {}.").format(plugin.device)) pin_msg.setWordWrap(True) pin_msg.setStyleSheet("color: red") settings_glayout.addWidget(pin_msg, 3, 1, 1, -1) # Settings tab - Homescreen homescreen_label = QLabel(_("Homescreen")) homescreen_change_button = QPushButton(_("Change...")) homescreen_clear_button = QPushButton(_("Reset")) homescreen_change_button.clicked.connect(change_homescreen) try: import PIL except ImportError: homescreen_change_button.setDisabled(True) homescreen_change_button.setToolTip( _("Required package 'PIL' is not available - Please install it or use the Trezor website instead." )) 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 {} x {} monochrome black and " "white image.").format(hs_cols, hs_rows)) 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 " "{} device can spend your CHI.").format(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 CHI " "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)
def __init__(self, main_win, outputs): WindowModalDialog.__init__(self, main_win, title=_("New scheduled payment"),) vbox = QVBoxLayout(self) self.setMinimumSize(400, 150) minute_label = HelpLabel(_('minute:'), _(''' Defines a specific minute for an hour. Allowed characters: "*" any value "," value list separator "-" range of values "/" step values 0-59 allowed values ''')) hour_label = HelpLabel(_('hour:'), _(''' Defines a specific hour during the day. Allowed characters: "*" any value "," value list separator "-" range of values "/" step values 0-23 allowed values ''')) day_label = HelpLabel(_('day of month:'), _(''' Defines the day number for the month. Allowed characters: "*" any value "," value list separator "-" range of values "/" step values 0-31 allowed values ''')) month_label = HelpLabel(_('month:'), _(''' Defines a month during the year. Allowed characters: "*" any value "," value list separator "-" range of values "/" step values 1-12 allowed values ''')) week_label = HelpLabel(_('day of week:'), _(''' Specifies the day of the week. Allowed characters: "*" any value "," value list separator "-" range of values "/" step values 0-6 allowed values ''')) self.minute_edit = QLineEdit('*') self.minute_edit.setFixedWidth(30) self.minute_edit.textChanged.connect(self.update_schedule_details) self.hour_edit = QLineEdit('*') self.hour_edit.setFixedWidth(30) self.hour_edit.textChanged.connect(self.update_schedule_details) self.day_edit = QLineEdit('*') self.day_edit.setFixedWidth(30) self.day_edit.textChanged.connect(self.update_schedule_details) self.month_edit = QLineEdit('*') self.month_edit.setFixedWidth(30) self.month_edit.textChanged.connect(self.update_schedule_details) self.week_edit = QLineEdit('*') self.week_edit.setFixedWidth(30) self.week_edit.textChanged.connect(self.update_schedule_details) grid = QGridLayout() grid.addWidget(minute_label, 0, 0, alignment=Qt.AlignCenter) grid.addWidget(hour_label, 0, 1, alignment=Qt.AlignCenter) grid.addWidget(day_label, 0, 2, alignment=Qt.AlignCenter) grid.addWidget(month_label, 0, 3, alignment=Qt.AlignCenter) grid.addWidget(week_label, 0, 4, alignment=Qt.AlignCenter) grid.addWidget(self.minute_edit, 1, 0, alignment=Qt.AlignCenter) grid.addWidget(self.hour_edit, 1, 1, alignment=Qt.AlignCenter) grid.addWidget(self.day_edit, 1, 2, alignment=Qt.AlignCenter) grid.addWidget(self.month_edit, 1, 3, alignment=Qt.AlignCenter) grid.addWidget(self.week_edit, 1, 4, alignment=Qt.AlignCenter) every_day = QPushButton('every day') every_day.clicked.connect(lambda: self.set_as_text('0 0 * * *')) every_week = QPushButton('every week') every_week.clicked.connect(lambda: self.set_as_text('0 0 * * 0')) every_month = QPushButton('every month') every_month.clicked.connect(lambda: self.set_as_text('0 0 1 * *')) every_year = QPushButton('every year') every_year.clicked.connect(lambda: self.set_as_text('0 0 1 1 *')) self.schedule_details = QLabel('') vbox.addLayout(grid) vbox.addLayout(Buttons(every_day, every_week, every_month, every_year)) vbox.addWidget(self.schedule_details) vbox.addStretch() vbox.addLayout(Buttons(CloseButton(self), OkButton(self))) self.update_schedule_details()
def build_gui(self): vbox = QVBoxLayout() self.setLayout(vbox) grid = QGridLayout() vbox.addLayout(grid) self.amount_label = QLabel('') grid.addWidget(QLabel(_("Target for confirmation")), 0, 0) self.qtarget = QDateTimeEdit(QDateTime.currentDateTime().addSecs( int(self.main_window.config.get('bitpost_target_interval')) * 60)) grid.addWidget(self.qtarget, 0, 1) self.asap_check = QCheckBox("ASAP") self.asap_check.clicked.connect(self.toggle_target) grid.addWidget(self.asap_check, 0, 2) grid.addWidget(QLabel(_("Maximum Fee")), 2, 0) self.max_fees = QLineEdit( str(self.main_window.config.get('bitpost_max_fee'))) self.max_fees.textChanged.connect(self.change_max_fees) grid.addWidget(self.max_fees, 2, 1) self.fee_combo = QComboBox() fee_combo_values = get_fee_units( self.main_window, self.main_window.config.get('bitpost_max_fee_unit')) self.fee_combo.addItems(fee_combo_values) grid.addWidget(self.fee_combo, 2, 2) self.schedule_check = QCheckBox(_("Schedule transaction")) self.schedule_check.clicked.connect(self.toggle_delay) grid.addWidget(self.schedule_check, 3, 0, 1, -1) self.qdelay = QDateTimeEdit(QDateTime.currentDateTime()) grid.addWidget(self.qdelay, 4, 0) sp_retain = QSizePolicy(self.qdelay.sizePolicy()) sp_retain.setRetainSizeWhenHidden(True) self.qdelay.setSizePolicy(sp_retain) self.qdelay.setVisible(False) self.message_label = QLabel(self.default_message()) grid.addWidget(self.message_label, 9, 0, 1, -1) self.pw_label = QLabel(_('Password')) self.pw_label.setVisible(self.password_required) self.pw = PasswordLineEdit() self.pw.setVisible(self.password_required) grid.addWidget(self.pw_label, 11, 0) grid.addWidget(self.pw, 11, 1, 1, -1) self.send_button = QPushButton(_('Send')) self.send_button.clicked.connect(self.on_send) self.send_button.setDefault(True) self.preview_button = QPushButton(_('Preview')) self.preview_button.clicked.connect(self.on_preview) self.preview_button.setDefault(True) vbox.addLayout( Buttons(CancelButton(self), self.preview_button, self.send_button)) # set default to ASAP checked self.asap_check.setChecked(True) self.toggle_target() self.update() self.is_send = False