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 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 __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 __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 create_proposal(self): manager = self.parent.masternode_manager try: proposal = self.create_proposal_from_widgets() except Exception as e: return QMessageBox.critical(self, _('Error'), _(str(e))) pw = None if manager.wallet.use_encryption: pw = self.parent.password_dialog(msg=_( 'Please enter your password to create a budget proposal.')) if pw is None: return manager.add_proposal(proposal) def sign_done(proposal, tx): print_error('proposal tx sign done: %s' % proposal.proposal_name) if tx: label = _('Budget Proposal Tx: ') + proposal.proposal_name self.parent.broadcast_transaction(tx, label) self.parent.masternode_manager.save() self.create_proposal_tx(proposal, pw, sign_done)
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 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 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 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 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 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 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 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 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 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 Sibcoin in it!") if not self.question( msg, title=title, icon=QMessageBox.Critical): return invoke_client('wipe_device', unpair_after=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 refresh_headers(self): headers = [ '', '', _('Date'), _('Description'), _('Amount'), _('Balance') ] run_hook('history_tab_headers', headers) self.update_headers(headers)
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 SIB 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=None): super(ProposalsTreeWidget, self).__init__(parent, self.create_menu, [ _('Name'), _('URL'), _('Yes Votes'), _('No Votes'), _('Start Block'), _('End Block'), _('Amount'), _('Address'), _('Fee Tx') ], 0) header = self.header() header.setResizeMode(ProposalsModel.NAME, QHeaderView.ResizeToContents) header.setResizeMode(ProposalsModel.URL, QHeaderView.Stretch) header.setResizeMode(ProposalsModel.YES_COUNT, QHeaderView.ResizeToContents) header.setResizeMode(ProposalsModel.NO_COUNT, QHeaderView.ResizeToContents) header.setResizeMode(ProposalsModel.ADDRESS, QHeaderView.ResizeToContents) header.setResizeMode(ProposalsModel.TXID, QHeaderView.ResizeToContents) self.model = ProposalsModel()
def __init__(self, parent=None): super(ProposalsModel, self).__init__(parent) self.proposals = [] headers = [ { Qt.DisplayRole: _('Name'), }, { Qt.DisplayRole: _('URL'), }, { Qt.DisplayRole: _('Yes Votes'), }, { Qt.DisplayRole: _('No Votes'), }, { Qt.DisplayRole: _('Start Block'), }, { Qt.DisplayRole: _('End Block'), }, { Qt.DisplayRole: _('Amount'), }, { Qt.DisplayRole: _('Address'), }, { Qt.DisplayRole: _('Fee Tx'), }, ] for d in headers: d[Qt.EditRole] = d[Qt.DisplayRole] self.headers = headers
def __init__(self, parent, seed, imported_keys): WindowModalDialog.__init__(self, parent, ('Electrum-Sibcoin - ' + _('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 __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 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-Sibcoin"), 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 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 Sibcoin 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 __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 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