def calibration_dialog(self, window): d = WindowModalDialog(window, _("Cosigner Pool Settings")) d.setMinimumSize(150, 100) vbox = QVBoxLayout(d) purge = QPushButton(_("Purge Transactions")) purge.clicked.connect(partial(self.purge_transaction, window)) purge.setIcon(read_QIcon("warning.png")) vbox.addWidget(purge) vbox.addWidget(QLabel(_('Wallet Owner:'))) grid = QGridLayout() vbox.addLayout(grid) grid.addWidget(QLabel(_('Name:')), 0, 0) name = QLineEdit() name.setText(self.config.get('wallet_owner', '')) grid.addWidget(name, 0, 1) sync = QPushButton(_("Sync Name")) sync.clicked.connect(partial(self.sync_name, name, window)) vbox.addWidget(sync) status = QPushButton(_("Tx. Status")) status.clicked.connect(partial(self.tx_status_dialog, window)) vbox.addWidget(status) vbox.addStretch() vbox.addSpacing(13) vbox.addLayout(Buttons(CloseButton(d), OkButton(d))) if not d.exec_(): return
def calibration_dialog(self, window): d = WindowModalDialog(window, _("Cosigner Pool Settings")) d.setMinimumSize(150, 100) vbox = QVBoxLayout(d) purge = QPushButton(_("Purge Transactions")) purge.clicked.connect(self.purge_transaction) vbox.addWidget(purge) vbox.addWidget(QLabel(_('Wallet Owner:'))) grid = QGridLayout() vbox.addLayout(grid) grid.addWidget(QLabel(_('Name:')), 0, 0) name = QLineEdit() name.setText(self.config.get('wallet_owner', '')) grid.addWidget(name, 0, 1) save = QPushButton(_("Save Name")) save.clicked.connect(lambda: self.config.set_key('wallet_owner', name.text())) vbox.addWidget(save) sync = QPushButton(_("Sync Name")) sync.clicked.connect(self.sync_name) vbox.addWidget(sync) vbox.addStretch() vbox.addSpacing(13) vbox.addLayout(Buttons(CloseButton(d), OkButton(d))) if not d.exec_(): return
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 tx_status_dialog(self, window): d = QDialog(window) d.setWindowTitle(_("Transaction Status")) d.setMinimumSize(600, 300) vbox = QVBoxLayout(d) status_header = 'No transaction in progress' status = '' for window, xpub, K, _hash in self.cosigner_list: cosigner = server.get(_hash + '_name') signed = True if server.get(_hash + '_signed') else False signing = True if server.get(_hash + '_lock') else False if signed: status_header = 'Transaction in progress' if signed: message = 'Signed' elif signing: message = 'Signing' else: message = 'Not signed' status += f'<br><br> {cosigner}: <b>{message}</b>' for key, _hash, window in self.keys: cosigner = server.get(_hash + '_name') signed = True if server.get(_hash + '_signed') else False signing = True if server.get(_hash + '_lock') else False if signed: status_header = 'Transaction in progress' if signed: message = 'Signed' elif signing: message = 'Signing' else: message = 'Not signed' status += f'<br><br> You: <b>{message}</b>' self.tx_status = QLabel() vbox.addWidget(self.tx_status) self.tx_status.setTextFormat(Qt.RichText) self.tx_status.setText( _("<b>Transaction Status</b>") + ': ' + status_header + status) self.tx_status.show() vbox.addStretch() vbox.addSpacing(13) vbox.addLayout(Buttons(CloseButton(d))) d.setModal(True) d.show()
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 {}").format(e) + "\n" + _("Please check your connection and credentials."))) check_connection.start()
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 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("trustedcoin-status.png"))) 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 tx_status_dialog(self, window): d = QDialog(window) d.setWindowTitle(_("Transaction Status")) d.setMinimumSize(600, 300) vbox = QVBoxLayout(d) status_header = 'No transaction in progress' status = '' data = server.get(self.wallet_hash) loads = json.loads(data) if data else {} lock = server.lock locked_by = lock.get('xpub') if lock else None signed_by = loads.get('signed', []) for _hash in server.cosigners(): name = server.get(_hash+'_name') if not name or len(name) < 1: name = _hash[0:10] + '...' + _hash[-1:-5:-1] signed = True if _hash in signed_by else False signing = True if _hash == locked_by else False if signed or signing: status_header = 'Transaction in progress' if signed: message = 'Signed' elif signing: message = 'Signing' else: message = 'Not signed' status += f'<br><br> {name}: <b>{message}</b>' for _hash in server.xpub(): signed = True if _hash in signed_by else False signing = True if _hash == locked_by else False if signed or signing: status_header = 'Transaction in progress' if signed: message = 'Signed' elif signing: message = 'Signing' else: message = 'Not signed' status += f'<br><br> You: <b>{message}</b>' self.tx_status = QLabel() vbox.addWidget(self.tx_status) self.tx_status.setTextFormat(Qt.RichText) self.tx_status.setText(_("<b>Transaction Status</b>") + ': ' + status_header + status) self.tx_status.show() vbox.addStretch() vbox.addSpacing(13) vbox.addLayout(Buttons(CloseButton(d))) d.setModal(True) d.show()
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 " "EXOS-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 EXOS-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 EXOS 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 EXOS 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 EXOS.").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 EXOS " "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, window, plugin, keystore, device_id): title = _("{} Settings").format(plugin.device) super(CKCCSettingsDialog, self).__init__(window, title) self.setMaximumWidth(540) devmgr = plugin.device_manager() config = devmgr.config handler = keystore.handler self.thread = thread = keystore.thread def connect_and_doit(): client = devmgr.client_by_id(device_id) if not client: raise RuntimeError("Device not connected") return client body = QWidget() body_layout = QVBoxLayout(body) grid = QGridLayout() grid.setColumnStretch(2, 1) # see <http://doc.qt.io/archives/qt-4.8/richtext-html-subset.html> title = QLabel('''<center> <span style="font-size: x-large">Coldcard Wallet</span> <br><span style="font-size: medium">from Coinkite Inc.</span> <br><a href="https://coldcardwallet.com">coldcardwallet.com</a>''') title.setTextInteractionFlags(Qt.LinksAccessibleByMouse) grid.addWidget(title, 0, 0, 1, 2, Qt.AlignHCenter) y = 3 rows = [ ('fw_version', _("Firmware Version")), ('fw_built', _("Build Date")), ('bl_version', _("Bootloader")), ('xfp', _("Master Fingerprint")), ('serial', _("USB Serial")), ] for row_num, (member_name, label) in enumerate(rows): widget = QLabel('<tt>000000000000') widget.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard) grid.addWidget(QLabel(label), y, 0, 1, 1, Qt.AlignRight) grid.addWidget(widget, y, 1, 1, 1, Qt.AlignLeft) setattr(self, member_name, widget) y += 1 body_layout.addLayout(grid) upg_btn = QPushButton('Upgrade') #upg_btn.setDefault(False) def _start_upgrade(): thread.add(connect_and_doit, on_success=self.start_upgrade) upg_btn.clicked.connect(_start_upgrade) y += 3 grid.addWidget(upg_btn, y, 0) grid.addWidget(CloseButton(self), y, 1) dialog_vbox = QVBoxLayout(self) dialog_vbox.addWidget(body) # Fetch values and show them thread.add(connect_and_doit, on_success=self.show_values)