def toggle_passphrase(self): if self.features.passphrase_protection: self.msg = _("Confirm on your %s device to disable passphrases") else: self.msg = _("Confirm on your %s device to enable passphrases") enabled = not self.features.passphrase_protection self.apply_settings(use_passphrase=enabled)
def __init__(self, parent, address): WindowModalDialog.__init__(self, parent, _("Address")) self.address = address self.parent = parent self.config = parent.config self.wallet = parent.wallet self.app = parent.app self.saved = True self.setMinimumWidth(700) vbox = QVBoxLayout() self.setLayout(vbox) vbox.addWidget(QLabel(_("Address:"))) self.addr_e = ButtonsLineEdit(self.address) self.addr_e.addCopyButton(self.app) self.addr_e.addButton(":icons/qrcode.png", self.show_qr, _("Show QR Code")) self.addr_e.setReadOnly(True) vbox.addWidget(self.addr_e) vbox.addWidget(QLabel(_("History"))) self.hw = HistoryWidget(self.parent) self.hw.get_domain = self.get_domain vbox.addWidget(self.hw) vbox.addStretch(1) vbox.addLayout(Buttons(CloseButton(self))) self.format_amount = self.parent.format_amount self.hw.update()
def query_multisig(self, action): cw = CosignWidget(2, 2) m_edit = QSpinBox() n_edit = QSpinBox() m_edit.setValue(2) n_edit.setValue(2) n_edit.setMinimum(2) n_edit.setMaximum(15) m_edit.setMinimum(1) m_edit.setMaximum(2) n_edit.valueChanged.connect(m_edit.setMaximum) n_edit.valueChanged.connect(cw.set_n) m_edit.valueChanged.connect(cw.set_m) hbox = QHBoxLayout() hbox.addWidget(QLabel(_('Require'))) hbox.addWidget(m_edit) hbox.addWidget(QLabel(_('of'))) hbox.addWidget(n_edit) hbox.addWidget(QLabel(_('signatures'))) hbox.addStretch(1) vbox = QVBoxLayout() vbox.addWidget(cw) vbox.addWidget( WWLabel( _("Choose the number of signatures needed " "to unlock funds in your wallet:"))) vbox.addLayout(hbox) self.set_main_layout(vbox, _("Multi-Signature Wallet")) m = int(m_edit.value()) n = int(n_edit.value()) wallet_type = '%dof%d' % (m, n) return wallet_type
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 create_layout(self): self.masternodes_widget = MasternodesWidget(self.manager) self.tabs = QTabWidget() self.tabs.addTab(self.create_view_masternode_tab(), _('View Masternode')) self.tabs.addTab(self.create_collateral_tab(), _('Choose Collateral')) self.tabs.addTab(self.create_sign_announce_tab(), _('Activate Masternode')) self.tabs.addTab(self.create_masternode_conf_tab(), _('Masternode.conf')) # Disabled until API is stable. # self.tabs.addTab(self.create_vote_tab(), _('Vote')) # Connect to the selection signal so we can update the widget mapper. self.masternodes_widget.view.selectionModel().selectionChanged.connect( self.on_view_selection_changed) bottom_buttons = util.Buttons(util.CloseButton(self)) vbox = QVBoxLayout() vbox.addWidget(QLabel(_('Masternodes:'))) vbox.addWidget(self.masternodes_widget, stretch=1) vbox.addWidget(self.tabs) vbox.addLayout(bottom_buttons) self.setLayout(vbox)
def save_current_masternode(self, as_new=False): """Save the masternode that is being viewed. If as_new is True, a new masternode will be created. """ delegate_privkey = str(self.masternode_editor.delegate_key_edit.text()) try: self.manager.import_masternode_delegate(delegate_privkey) delegate_pubkey = bitcoin.public_key_from_private_key( delegate_privkey) except Exception: # Show an error if the private key is invalid and not an empty string. if delegate_privkey: QMessageBox.warning( self, _('Warning'), _('Ignoring invalid delegate private key.')) delegate_pubkey = '' alias = str(self.masternode_editor.alias_edit.text()) # Construct a new masternode. if as_new: kwargs = self.masternode_editor.get_masternode_args() kwargs['delegate_key'] = delegate_pubkey del kwargs['vin'] self.mapper.revert() self.masternodes_widget.add_masternode( MasternodeAnnounce(**kwargs)) else: self.mapper.submit() self.manager.save() self.masternodes_widget.select_masternode(alias)
def sign_announce(self, alias): """Sign an announce for alias. This is called by SignAnnounceWidget.""" pw = None if self.manager.wallet.use_encryption: pw = self.gui.password_dialog(msg=_( 'Please enter your password to activate masternode "%s".' % alias)) if pw is None: return self.sign_announce_widget.sign_button.setEnabled(False) def sign_thread(): return self.manager.sign_announce(alias, pw) def on_sign_successful(mn): self.print_msg('Successfully signed Masternode Announce.') self.send_announce(alias) # Proceed to broadcasting the announcement, or re-enable the button. def on_sign_error(err): self.print_error('Error signing MasternodeAnnounce:') # Print traceback information to error log. self.print_error(''.join(traceback.format_tb(err[2]))) self.print_error(''.join( traceback.format_exception_only(err[0], err[1]))) self.sign_announce_widget.sign_button.setEnabled(True) util.WaitingDialog(self, _('Signing Masternode Announce...'), sign_thread, on_sign_successful, on_sign_error)
def value_str(self, satoshis, rate): if satoshis is None: # Can happen with incomplete history return _("Unknown") if rate: value = Decimal(satoshis) / COIN * Decimal(rate) return "%s" % (self.ccy_amount_str(value, True)) return _("No data")
def task(): wallet.wait_until_synchronized() if wallet.is_found(): msg = _("Recovery successful") else: msg = _("No transactions found for this seed") self.emit(QtCore.SIGNAL('synchronized'), msg)
def closeEvent(self, event): if (self.prompt_if_unsaved and not self.saved and not self.question( _('This transaction is not saved. Close anyway?'), title=_("Warning"))): event.ignore() else: event.accept() dialogs.remove(self)
def on_vote_successful(result): errmsg, res = result if res: QMessageBox.information(self, _('Success'), _('Successfully voted')) else: QMessageBox.critical(self, _('Error Voting'), _(errmsg)) self.proposals_widget.editor.vote_button.setEnabled(True)
def set_pin(self, remove): if remove: self.msg = _("Confirm on your %s device to disable PIN protection") elif self.features.pin_protection: self.msg = _("Confirm on your %s device to change your PIN") else: self.msg = _("Confirm on your %s device to set a PIN") self.change_pin(remove)
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 Dash in it!") if not self.question( msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=True)
def save(self): name = 'signed_%s.txn' % ( self.tx.hash()[0:8]) if self.tx.is_complete() else 'unsigned.txn' fileName = self.main_window.getSaveFileName( _("Select where to save your signed transaction"), name, "*.txn") if fileName: with open(fileName, "w+") as f: f.write(json.dumps(self.tx.as_dict(), indent=4) + '\n') self.show_message(_("Transaction saved successfully")) self.saved = True
def export_history_dialog(self, window, hbox): wallet = window.wallet history = wallet.get_history() if len(history) > 0: b = QPushButton(_("Preview plot")) hbox.addWidget(b) b.clicked.connect(lambda: self.do_plot(wallet, history)) else: b = QPushButton(_("No history to plot")) hbox.addWidget(b)
def delete_current_masternode(self): """Delete the masternode that is being viewed.""" mn = self.selected_masternode() if QMessageBox.question( self, _('Delete'), _('Do you want to remove the masternode configuration for') + ' %s?' % mn.alias, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.Yes: self.masternodes_widget.remove_masternode(mn.alias) self.masternodes_widget.view.selectRow(0)
def __init__(self, parent=None): super(MasternodeEditor, self).__init__(parent) self.alias_edit = QLineEdit() self.alias_edit.setPlaceholderText( _('Enter a name for this masternode')) self.vin_edit = PrevOutWidget() self.addr_edit = NetworkAddressWidget() self.delegate_key_edit = QLineEdit() self.delegate_key_edit.setFont(QFont(util.MONOSPACE_FONT)) self.delegate_key_edit.setPlaceholderText( _('Your masternode\'s private key')) self.protocol_version_edit = QLineEdit() self.protocol_version_edit.setText('70201') self.status_edit = QLineEdit() self.status_edit.setPlaceholderText(_('Masternode status')) self.status_edit.setReadOnly(True) form = QFormLayout() form.addRow(_('Alias:'), self.alias_edit) form.addRow(_('Status:'), self.status_edit) form.addRow(_('Collateral ION Output:'), self.vin_edit) form.addRow(_('Masternode Private Key:'), self.delegate_key_edit) form.addRow(_('Address:'), self.addr_edit) form.addRow(_('Protocol Version:'), self.protocol_version_edit) self.setLayout(form)
def __init__(self, parent, seed, imported_keys): WindowModalDialog.__init__(self, parent, ('electrum-ion - ' + _('Seed'))) self.setMinimumWidth(400) vbox = QVBoxLayout(self) vbox.addLayout(SeedWarningLayout(seed).layout()) if imported_keys: warning = ("<b>" + _("WARNING") + ":</b> " + _("Your wallet contains imported keys. These keys " "cannot be recovered from your seed.") + "</b><p>") vbox.addWidget(WWLabel(warning)) vbox.addLayout(Buttons(CloseButton(self)))
def on_done(): msg = '' for proposal_name, errmsg, success in results: if success: msg += '<b>' + proposal_name + '</b>' + _(': submitted successfully.') else: msg += '<b>' + proposal_name + '</b>' + _(': failed! "%s"' % errmsg) msg += '\n' QMessageBox.information(self, _('Results'), msg) self.update_unsubmitted_proposals() self.parent.masternode_manager.save()
def build_tray_menu(self): # Avoid immediate GC of old menu when window closed via its action self.old_menu = self.tray.contextMenu() m = QMenu() for window in self.windows: submenu = m.addMenu(window.wallet.basename()) submenu.addAction(_("Show/Hide"), window.show_or_hide) submenu.addAction(_("Close"), window.close) m.addAction(_("Dark/Light"), self.toggle_tray_icon) m.addSeparator() m.addAction(_("Exit electrum-ion"), self.close) self.tray.setContextMenu(m)
def callback_PinMatrixRequest(self, msg): if msg.type == 2: msg = _("Enter a new PIN for your %s:") elif msg.type == 3: msg = (_("Re-enter the new PIN for your %s.\n\n" "NOTE: the positions of the numbers have changed!")) else: msg = _("Enter your current %s PIN:") pin = self.handler.get_pin(msg % self.device) if not pin: return self.proto.Cancel() return self.proto.PinMatrixAck(pin=pin)
def __init__(self, parent=None): super(NetworkAddressWidget, self).__init__(parent) self.ip_edit = QLineEdit() self.port_edit = QSpinBox() self.port_edit.setRange(0, 99999) hbox = QHBoxLayout() hbox.setContentsMargins(0, 0, 0, 0) hbox.addWidget(QLabel(_('IP:'))) hbox.addWidget(self.ip_edit, stretch=1) hbox.addWidget(QLabel(_('Port:'))) hbox.addWidget(self.port_edit, stretch=1) self.setLayout(hbox)
def callback_PassphraseRequest(self, req): if self.creating_wallet: msg = _("Enter a passphrase to generate this wallet. Each time " "you use this wallet your %s will prompt you for the " "passphrase. If you forget the passphrase you cannot " "access the Dash in the wallet.") % self.device else: msg = _("Enter the passphrase to unlock this wallet:") passphrase = self.handler.get_passphrase(msg, self.creating_wallet) if passphrase is None: return self.proto.Cancel() passphrase = BIP44_Wallet.normalize_passphrase(passphrase) return self.proto.PassphraseAck(passphrase=passphrase)
def create_view_masternode_tab(self): """Create the tab used to view masternodes.""" desc = ' '.join([ 'In this tab, you can view your masternodes and fill in required data about them.', 'The collateral payment for a masternode can be specified using the "Choose Collateral" tab.', ]) desc = QLabel(_(desc)) desc.setWordWrap(True) self.masternode_editor = editor = MasternodeEditor() model = self.masternodes_widget.proxy_model self.mapper = mapper = QDataWidgetMapper() editor.alias_edit.textChanged.connect(self.on_editor_alias_changed) mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) mapper.setModel(model) mapper.addMapping(editor.alias_edit, MasternodesModel.ALIAS) mapper.addMapping(editor.status_edit, MasternodesModel.STATUS) editor.vin_edit.setReadOnly(True) mapper.addMapping(editor.vin_edit, MasternodesModel.VIN, 'string') mapper.addMapping(editor.addr_edit, MasternodesModel.ADDR, 'string') mapper.addMapping(editor.delegate_key_edit, MasternodesModel.DELEGATE) mapper.addMapping(editor.protocol_version_edit, MasternodesModel.PROTOCOL_VERSION) self.save_new_masternode_button = QPushButton('Save As New Masternode') self.save_new_masternode_button.clicked.connect( lambda: self.save_current_masternode(as_new=True)) self.save_masternode_button = QPushButton(_('Save Masternode')) self.save_masternode_button.clicked.connect( self.save_current_masternode) self.delete_masternode_button = QPushButton(_('Delete Masternode')) self.delete_masternode_button.clicked.connect( self.delete_current_masternode) vbox = QVBoxLayout() vbox.addWidget(desc) vbox.addWidget(editor) vbox.addStretch(1) vbox.addLayout( util.Buttons(self.delete_masternode_button, self.save_new_masternode_button, self.save_masternode_button)) w = QWidget() w.setLayout(vbox) return w
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 load_wallet(self, wallet, window): if type(wallet) != BTChipWallet: return wallet.handler = BTChipQTHandler(window) if self.btchip_is_connected(wallet): if not wallet.check_proper_device(): window.show_error( _("This wallet does not match your Ledger device")) wallet.force_watching_only = True else: window.show_error( _("Ledger device not detected.\nContinuing in watching-only mode." )) wallet.force_watching_only = True
def __init__(self, main_widget, parent=None): super(ProposalEditor, self).__init__(parent) self.main_widget = main_widget self.name_edit = QLineEdit() self.url_edit = QLineEdit() self.start_block_edit = QLineEdit() self.end_block_edit = QLineEdit() self.amount_edit = QLineEdit() self.address_edit = QLineEdit() self.txid_edit = QLineEdit() for i in [self.name_edit, self.url_edit, self.start_block_edit, self.end_block_edit, self.amount_edit, self.address_edit, self.txid_edit]: i.setReadOnly(True) self.mapper = QDataWidgetMapper() self.mapper.setModel(self.main_widget.proxy_model) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.addMapping(self.name_edit, ProposalsModel.NAME) self.mapper.addMapping(self.url_edit, ProposalsModel.URL) self.mapper.addMapping(self.start_block_edit, ProposalsModel.START_BLOCK) self.mapper.addMapping(self.end_block_edit, ProposalsModel.END_BLOCK) self.mapper.addMapping(self.amount_edit, ProposalsModel.AMOUNT) self.mapper.addMapping(self.address_edit, ProposalsModel.ADDRESS) self.mapper.addMapping(self.txid_edit, ProposalsModel.TXID) block_hbox = QHBoxLayout() block_hbox.addWidget(self.start_block_edit) block_hbox.addWidget(QLabel(' - ')) block_hbox.addWidget(self.end_block_edit) self.vote_combo = QComboBox() self.vote_combo.addItem(_('Yes')) self.vote_combo.addItem(_('No')) self.vote_button = QPushButton(_('Vote')) self.vote_button.clicked.connect(self.cast_vote) vote_hbox = util.Buttons(self.vote_combo, self.vote_button) form = QFormLayout() form.addRow(_('Name:'), self.name_edit) form.addRow(_('URL:'), self.url_edit) form.addRow(_('Blocks:'), block_hbox) form.addRow(_('Monthly Payment:'), self.amount_edit) form.addRow(_('Payment Address:'), self.address_edit) form.addRow(_('Fee TxID:'), self.txid_edit) form.addRow(_('Vote:'), vote_hbox) self.setLayout(form)
def settings_dialog(self, window): d = WindowModalDialog(window, _("Exchange Rate Settings")) layout = QGridLayout(d) layout.addWidget(QLabel(_('Exchange rate API: ')), 0, 0) layout.addWidget(QLabel(_('Currency: ')), 1, 0) layout.addWidget(QLabel(_('History Rates: ')), 2, 0) # Currency list self.ccy_combo = QComboBox() self.ccy_combo.currentIndexChanged.connect(self.on_ccy_combo_change) self.populate_ccy_combo() def on_change_ex(idx): exchange = str(combo_ex.currentText()) if exchange != self.exchange.name(): self.set_exchange(exchange) self.hist_checkbox_update() def on_change_hist(checked): if checked: self.config.set_key('history_rates', 'checked') self.get_historical_rates() else: self.config.set_key('history_rates', 'unchecked') self.emit(SIGNAL('refresh_headers')) def ok_clicked(): self.timeout = 0 self.ccy_combo = None d.accept() combo_ex = QComboBox() combo_ex.addItems(sorted(self.exchanges.keys())) combo_ex.setCurrentIndex(combo_ex.findText(self.config_exchange())) combo_ex.currentIndexChanged.connect(on_change_ex) self.hist_checkbox = QCheckBox() self.hist_checkbox.stateChanged.connect(on_change_hist) self.hist_checkbox_update() ok_button = QPushButton(_("OK")) ok_button.clicked.connect(lambda: ok_clicked()) layout.addWidget(self.ccy_combo, 1, 1) layout.addWidget(combo_ex, 0, 1) layout.addWidget(self.hist_checkbox, 2, 1) layout.addWidget(ok_button, 3, 1) return d.exec_()
def update(self, proposals, main_window): item = self.currentItem() current_proposal = item.data(ProposalsModel.TXID, Qt.UserRole).toString() if item else None self.model.set_proposals(proposals) self.clear() row_count = self.model.rowCount() if row_count < 1: return for r in range(row_count): get_data = lambda col, row=r: self.model.data(self.model.index(row, col)) name = _(str(get_data(ProposalsModel.NAME).toString())) url = _(str(get_data(ProposalsModel.URL).toString())) yes_count = str(get_data(ProposalsModel.YES_COUNT).toString()) no_count = str(get_data(ProposalsModel.NO_COUNT).toString()) start_block = str(get_data(ProposalsModel.START_BLOCK).toString()) end_block = str(get_data(ProposalsModel.END_BLOCK).toString()) amount = str(get_data(ProposalsModel.AMOUNT).toString()) address = str(get_data(ProposalsModel.ADDRESS).toString()) txid = str(get_data(ProposalsModel.TXID).toString()) display_txid = '%s...%s' % (txid[0:8], txid[-8:]) item = QTreeWidgetItem( [name, url, yes_count, no_count, start_block, end_block, amount, address, display_txid] ) item.setFont(ProposalsModel.START_BLOCK, QFont(util.MONOSPACE_FONT)) item.setFont(ProposalsModel.END_BLOCK, QFont(util.MONOSPACE_FONT)) item.setFont(ProposalsModel.ADDRESS, QFont(util.MONOSPACE_FONT)) item.setFont(ProposalsModel.TXID, QFont(util.MONOSPACE_FONT)) if name: item.setData(ProposalsModel.NAME, Qt.UserRole, name) if txid: item.setData(ProposalsModel.TXID, Qt.UserRole, txid) is_my_proposal = False if main_window.masternode_manager.get_proposal(name) is not None: is_my_proposal = True if is_my_proposal: item.setBackground(ProposalsModel.NAME, QBrush(QColor(MY_PROPOSAL_COLOR))) item.setToolTip(ProposalsModel.NAME, _('You created this proposal.')) is_my_address = main_window.wallet.is_mine(address) if is_my_address: item.setBackground(ProposalsModel.ADDRESS, QBrush(QColor(MY_ADDRESS_COLOR))) item.setToolTip(ProposalsModel.ADDRESS, _('You own this address.')) self.addTopLevelItem(item) if current_proposal == name: self.setCurrentItem(item)
def on_send_successful(result): errmsg, was_announced = result if was_announced: self.print_msg( 'Successfully broadcasted MasternodeAnnounce for "%s"' % alias) QMessageBox.information( self, _('Success'), _('Masternode activated successfully.')) else: self.print_error('Failed to broadcast MasternodeAnnounce: %s' % errmsg) QMessageBox.critical(self, _('Error Sending'), _(errmsg)) self.masternodes_widget.refresh_items() self.masternodes_widget.select_masternode(alias)