def get_xpub(self, device_id, derivation, xtype, wizard): # this seems to be part of the pairing process only, not during normal ops? # base_wizard:on_hw_derivation if xtype not in self.SUPPORTED_XTYPES: raise ScriptTypeNotSupported( _('This type of script is not supported with {}.').format( self.device)) devmgr = self.device_manager() client = devmgr.client_by_id(device_id) client.handler = self.create_handler(wizard) client.ping_check() xpub = client.get_xpub(derivation, xtype) return xpub
def create_menu(self, position): idx = self.indexAt(position) item = self.model().itemFromIndex(idx) item_col0 = self.model().itemFromIndex( idx.sibling(idx.row(), self.Columns.DATE)) if not item or not item_col0: return key = item_col0.data(Qt.UserRole) column = idx.column() column_title = self.model().horizontalHeaderItem(column).text() column_data = item.text() status = self.parent.invoices.get_status(key) menu = QMenu(self) if column_data: menu.addAction( _("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data)) menu.addAction(_("Details"), lambda: self.parent.show_invoice(key)) if status == PR_UNPAID: menu.addAction(_("Pay Now"), lambda: self.parent.do_pay_invoice(key)) menu.addAction(_("Delete"), lambda: self.parent.delete_invoice(key)) menu.exec_(self.viewport().mapToGlobal(position))
def get_xpub(self, bip32_path, xtype): assert xtype in ColdcardPlugin.SUPPORTED_XTYPES print_error('[coldcard]', 'Derive xtype = %r' % xtype) xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000) # TODO handle timeout? # change type of xpub to the requested type try: __, depth, fingerprint, child_number, c, cK = deserialize_xpub(xpub) except InvalidMasterKeyVersionBytes: raise Exception(_('Invalid xpub magic. Make sure your {} device is set to the correct chain.') .format(self.device)) from None if xtype != 'standard': xpub = serialize_xpub(xtype, c, cK, depth, fingerprint, child_number) return xpub
def pin_changed(s): if len(s) < len(self.idxs): i = self.idxs[len(s)] addr = self.txdata['address'] if not constants.net.TESTNET: text = addr[:i] + '<u><b>' + addr[i:i+1] + '</u></b>' + addr[i+1:] else: # pin needs to be created from mainnet address addr_mainnet = bitcoin.script_to_address(bitcoin.address_to_script(addr), net=constants.BitcoinMainnet) addr_mainnet = addr_mainnet[:i] + '<u><b>' + addr_mainnet[i:i+1] + '</u></b>' + addr_mainnet[i+1:] text = str(addr) + '\n' + str(addr_mainnet) self.addrtext.setHtml(str(text)) else: self.addrtext.setHtml(_("Press Enter"))
def callback_PassphraseRequest(self, req): if req and hasattr(req, 'on_device') and req.on_device is True: return self.proto.PassphraseAck() if self.creating_wallet: msg = _("Enter a passphrase to generate this wallet. Each time " "you use this wallet your {} will prompt you for the " "passphrase. If you forget the passphrase you cannot " "access the namecoins in the wallet.").format(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 = bip39_normalize_passphrase(passphrase) ack = self.proto.PassphraseAck(passphrase=passphrase) length = len(ack.passphrase) if length > 50: self.handler.show_error( _("Too long passphrase ({} > 50 chars).").format(length)) return self.proto.Cancel() return ack
def show_address(self, wallet, address, keystore=None): if keystore is None: keystore = wallet.get_keystore() if not self.show_address_helper(wallet, address, keystore): return # Standard_Wallet => not multisig, must be bip32 if type(wallet) is not Standard_Wallet: keystore.handler.show_error(_('This function is only available for standard wallets when using {}.').format(self.device)) return sequence = wallet.get_address_index(address) txin_type = wallet.get_txin_type(address) keystore.show_address(sequence, txin_type)
def waiting_dialog_for_billing_info(self, window, *, on_finished=None): def task(): return self.request_billing_info(window.wallet, suppress_connection_error=False) def on_error(exc_info): e = exc_info[1] window.show_error("{header}\n{exc}\n\n{tor}" .format(header=_('Error getting TrustedCoin account info.'), exc=str(e), tor=_('If you keep experiencing network problems, try using a Tor proxy.'))) return WaitingDialog(parent=window, message=_('Requesting account info from TrustedCoin server...'), task=task, on_success=on_finished, on_error=on_error)
def initialize_device(self, device_id, wizard, handler): # Initialization method msg = _("Choose how you want to initialize your {}.\n\n" "The first two methods are secure as no secret information " "is entered into your computer.\n\n" "For the last two methods you input secrets on your keyboard " "and upload them to your {}, and so you should " "only do those on a computer you know to be trustworthy " "and free of malware.").format(self.device, self.device) choices = [ # Must be short as QT doesn't word-wrap radio button text (TIM_NEW, _("Let the device generate a completely new seed randomly")), (TIM_RECOVER, _("Recover from a seed you have previously written down")), ] def f(method): import threading settings = self.request_trezor_init_settings( wizard, method, device_id) t = threading.Thread(target=self._initialize_device_safe, args=(settings, method, device_id, wizard, handler)) t.setDaemon(True) t.start() exit_code = wizard.loop.exec_() if exit_code != 0: # this method (initialize_device) was called with the expectation # of leaving the device in an initialized state when finishing. # signal that this is not the case: raise UserCancelled() wizard.choice_dialog(title=_('Initialize Device'), message=msg, choices=choices, run_next=f)
def waiting_dialog( self, task, msg=_("Electrum-NMC is generating your addresses, please wait.")): def target(): task() self.emit(QtCore.SIGNAL('accept')) vbox = QVBoxLayout() self.waiting_label = QLabel(msg) vbox.addWidget(self.waiting_label) self.set_layout(vbox) t = threading.Thread(target=target) t.start() self.exec_()
def pw_changed(self): password = self.new_pw.text() if password: colors = { "Weak": "Red", "Medium": "Blue", "Strong": "Green", "Very Strong": "Green" } strength = check_password_strength(password) label = (_("Password Strength") + ": " + "<font color=" + colors[strength] + ">" + strength + "</font>") else: label = "" self.pw_strength.setText(label)
def request_otp_dialog(self, window, short_id, otp_secret, xpub3): vbox = QVBoxLayout() if otp_secret is not None: uri = "otpauth://totp/%s?secret=%s"%('trustedcoin.com', otp_secret) l = QLabel("Please scan the following QR code in Google Authenticator. You may as well use the following key: %s"%otp_secret) l.setWordWrap(True) vbox.addWidget(l) qrw = QRCodeWidget(uri) vbox.addWidget(qrw, 1) msg = _('Then, enter your Google Authenticator code:') else: label = QLabel( "This wallet is already registered with TrustedCoin. " "To finalize wallet creation, please enter your Google Authenticator Code. " ) label.setWordWrap(1) vbox.addWidget(label) msg = _('Google Authenticator code:') hbox = QHBoxLayout() hbox.addWidget(WWLabel(msg)) pw = AmountEdit(None, is_int = True) pw.setFocus(True) pw.setMaximumWidth(50) hbox.addWidget(pw) vbox.addLayout(hbox) cb_lost = QCheckBox(_("I have lost my Google Authenticator account")) cb_lost.setToolTip(_("Check this box to request a new secret. You will need to retype your seed.")) vbox.addWidget(cb_lost) cb_lost.setVisible(otp_secret is None) def set_enabled(): b = True if cb_lost.isChecked() else len(pw.text()) == 6 window.next_button.setEnabled(b) pw.textChanged.connect(set_enabled) cb_lost.toggled.connect(set_enabled) window.exec_layout(vbox, next_enabled=False, raise_on_cancel=False) self.check_otp(window, short_id, otp_secret, xpub3, pw.get_amount(), cb_lost.isChecked())
def export_psbt(self, dia): # Called from hook in transaction dialog tx = dia.tx if tx.is_complete(): # if they sign while dialog is open, it can transition from unsigned to signed, # which we don't support here, so do nothing return # can only expect Coldcard wallets to work with these files (right now) keystore = dia.wallet.get_keystore() assert type(keystore) == self.keystore_class # convert to PSBT raw_psbt = keystore.build_psbt(tx, wallet=dia.wallet) name = (dia.wallet.basename() + time.strftime('-%y%m%d-%H%M.psbt')).replace(' ', '-') fileName = dia.main_window.getSaveFileName(_("Select where to save the PSBT file"), name, "*.psbt") if fileName: with open(fileName, "wb+") as f: f.write(raw_psbt) dia.show_message(_("Transaction exported successfully")) dia.saved = True
def context_menu(self): view_menu = QMenu() themes_menu = view_menu.addMenu(_("&Themes")) selected_theme = self.actuator.selected_theme() theme_group = QActionGroup(self) for theme_name in self.actuator.theme_names(): theme_action = themes_menu.addAction(theme_name) theme_action.setCheckable(True) if selected_theme == theme_name: theme_action.setChecked(True) class SelectThemeFunctor: def __init__(self, theme_name, toggle_theme): self.theme_name = theme_name self.toggle_theme = toggle_theme def __call__(self, checked): if checked: self.toggle_theme(self.theme_name) delegate = SelectThemeFunctor(theme_name, self.toggle_theme) theme_action.toggled.connect(delegate) theme_group.addAction(theme_action) view_menu.addSeparator() show_receiving = view_menu.addAction(_("Show Receiving addresses")) show_receiving.setCheckable(True) show_receiving.toggled.connect(self.toggle_receiving_layout) show_receiving.setChecked(self.config.get("gui_show_receiving", False)) show_history = view_menu.addAction(_("Show History")) show_history.setCheckable(True) show_history.toggled.connect(self.show_history) show_history.setChecked(self.config.get("gui_show_history", False)) return view_menu
def __init__(self, prompt='>> ', startup_message='', parent=None): QtWidgets.QPlainTextEdit.__init__(self, parent) self.prompt = prompt self.history = [] self.namespace = {} self.construct = [] self.setGeometry(50, 75, 600, 400) self.setWordWrapMode(QtGui.QTextOption.WrapAnywhere) self.setUndoRedoEnabled(False) self.document().setDefaultFont( QtGui.QFont(MONOSPACE_FONT, 10, QtGui.QFont.Normal)) self.showMessage(startup_message) self.updateNamespace({'run': self.run_script}) self.set_json(False) warning_text = "<h1>{}</h1><br>{}<br><br>{}".format( _("Warning!"), _("Do not paste code here that you don't understand. Executing the wrong code could lead " "to your coins being irreversibly lost."), _("Click here to hide this message.")) self.messageOverlay = OverlayLabel(warning_text, self)
def on_reset_auth(self, wizard, short_id, seed, passphrase, xpub3): xprv1, xpub1, xprv2, xpub2 = self.xkeys_from_seed(seed, passphrase) if (wizard.storage.get('x1/')['xpub'] != xpub1 or wizard.storage.get('x2/')['xpub'] != xpub2): wizard.show_message(_('Incorrect seed')) return r = server.get_challenge(short_id) challenge = r.get('challenge') message = 'TRUSTEDCOIN CHALLENGE: ' + challenge def f(xprv): _, _, _, _, c, k = deserialize_xprv(xprv) pk = bip32_private_key([0, 0], k, c) key = ecc.ECPrivkey(pk) sig = key.sign_message(message, True) return base64.b64encode(sig).decode() signatures = [f(x) for x in [xprv1, xprv2]] r = server.reset_auth(short_id, challenge, signatures) new_secret = r.get('otp_secret') if not new_secret: wizard.show_message(_('Request rejected by server')) return self.request_otp_dialog(wizard, short_id, new_secret, xpub3)
def restore_choice(self, wizard, seed, passphrase): wizard.set_icon(':icons/trustedcoin-wizard.png') wizard.stack = [] title = _('Restore 2FA wallet') msg = ' '.join([ 'You are going to restore a wallet protected with two-factor authentication.', 'Do you want to keep using two-factor authentication with this wallet,', 'or do you want to disable it, and have two master private keys in your wallet?' ]) choices = [('keep', 'Keep'), ('disable', 'Disable')] f = lambda x: self.on_choice(wizard, seed, passphrase, x) wizard.choice_dialog(choices=choices, message=msg, title=title, run_next=f)
def seed_warning_msg(seed): return ''.join([ "<p>", _("Please save these {0} words on paper (order is important). "), _("This seed will allow you to recover your wallet in case " "of computer failure."), "</p>", "<b>" + _("WARNING") + ":</b>", "<ul>", "<li>" + _("Never disclose your seed.") + "</li>", "<li>" + _("Never type it on a website.") + "</li>", "<li>" + _("Do not store it electronically.") + "</li>", "</ul>" ]).format(len(seed.split()))
def callback_WordRequest(self, msg): if (msg.type is not None and msg.type in (self.types.WordRequestType.Matrix9, self.types.WordRequestType.Matrix6)): num = 9 if msg.type == self.types.WordRequestType.Matrix9 else 6 char = self.handler.get_matrix(num) if char == 'x': return self.proto.Cancel() return self.proto.WordAck(word=char) self.step += 1 msg = _("Step {}/24. Enter seed word as explained on " "your {}:").format(self.step, self.device) word = self.handler.get_word(msg) # Unfortunately the device can't handle self.proto.Cancel() return self.proto.WordAck(word=word)
def create_menu(self, position): self.selectedIndexes() item = self.currentItem() if not item: return column = self.currentColumn() tx_hash = item.data(0, Qt.UserRole) if not tx_hash: return tx = self.wallet.transactions.get(tx_hash) if not tx: return if column is 0: column_title = "ID" column_data = tx_hash else: column_title = self.headerItem().text(column) column_data = item.text(column) tx_URL = block_explorer_URL(self.config, 'tx', tx_hash) height = self.wallet.get_tx_height(tx_hash).height is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx) is_unconfirmed = height <= 0 pr_key = self.wallet.invoices.paid.get(tx_hash) menu = QMenu() if height == TX_HEIGHT_LOCAL: menu.addAction(_("Remove"), lambda: self.remove_local_tx(tx_hash)) menu.addAction(_("Copy {}").format(column_title), lambda: self.parent.app.clipboard().setText(column_data)) for c in self.editable_columns: menu.addAction(_("Edit {}").format(self.headerItem().text(c)), lambda bound_c=c: self.editItem(item, bound_c)) menu.addAction(_("Details"), lambda: self.parent.show_transaction(tx)) if is_unconfirmed and tx: # note: the current implementation of RBF *needs* the old tx fee rbf = is_mine and not tx.is_final() and fee is not None if rbf: menu.addAction(_("Increase fee"), lambda: self.parent.bump_fee_dialog(tx)) else: child_tx = self.wallet.cpfp(tx, 0) if child_tx: menu.addAction(_("Child pays for parent"), lambda: self.parent.cpfp(tx, child_tx)) if pr_key: menu.addAction(self.icon_cache.get(":icons/seal"), _("View invoice"), lambda: self.parent.show_invoice(pr_key)) if tx_URL: menu.addAction(_("View on block explorer"), lambda: webbrowser.open(tx_URL)) menu.exec_(self.viewport().mapToGlobal(position))
def get_xpub(self, bip32_path, xtype): assert xtype in ColdcardPlugin.SUPPORTED_XTYPES print_error('[coldcard]', 'Derive xtype = %r' % xtype) xpub = self.dev.send_recv(CCProtocolPacker.get_xpub(bip32_path), timeout=5000) # TODO handle timeout? # change type of xpub to the requested type try: node = BIP32Node.from_xkey(xpub) except InvalidMasterKeyVersionBytes: raise UserFacingException( _('Invalid xpub magic. Make sure your {} device is set to the correct chain.' ).format(self.device)) from None if xtype != 'standard': xpub = node._replace(xtype=xtype).to_xpub() return xpub
def address_field(addresses): hbox = QHBoxLayout() address_e = QLineEdit() if addresses: address_e.setText(addresses[0]) def func(): i = addresses.index(str(address_e.text())) + 1 i = i % len(addresses) address_e.setText(addresses[i]) button = QPushButton(_('Address')) button.clicked.connect(func) hbox.addWidget(button) hbox.addWidget(address_e) return hbox, address_e
def transaction_dialog(self, dia): # see gui/qt/transaction_dialog.py keystore = dia.wallet.get_keystore() if type(keystore) != self.keystore_class: # not a Coldcard wallet, hide feature return # - add a new button, near "export" btn = QPushButton(_("Save PSBT")) btn.clicked.connect(lambda unused: self.export_psbt(dia)) if dia.tx.is_complete(): # but disable it for signed transactions (nothing to do if already signed) btn.setDisabled(True) dia.sharing_buttons.append(btn)
def _initialize_device(self, settings, method, device_id, wizard, handler): item, label, pin_protection, passphrase_protection, recovery_type = settings if method == TIM_RECOVER and recovery_type == RECOVERY_TYPE_SCRAMBLED_WORDS: handler.show_error(_( "You will be asked to enter 24 words regardless of your " "seed's actual length. If you enter a word incorrectly or " "misspell it, you cannot change it or go back - you will need " "to start again from the beginning.\n\nSo please enter " "the words carefully!"), blocking=True) language = 'english' devmgr = self.device_manager() client = devmgr.client_by_id(device_id) if method == TIM_NEW: strength = 64 * (item + 2) # 128, 192 or 256 u2f_counter = 0 skip_backup = False client.reset_device(True, strength, passphrase_protection, pin_protection, label, language, u2f_counter, skip_backup) elif method == TIM_RECOVER: word_count = 6 * (item + 2) # 12, 18 or 24 client.step = 0 if recovery_type == RECOVERY_TYPE_SCRAMBLED_WORDS: recovery_type_trezor = self.types.RecoveryDeviceType.ScrambledWords else: recovery_type_trezor = self.types.RecoveryDeviceType.Matrix client.recovery_device(word_count, passphrase_protection, pin_protection, label, language, type=recovery_type_trezor) if recovery_type == RECOVERY_TYPE_MATRIX: handler.close_matrix_dialog() elif method == TIM_MNEMONIC: pin = pin_protection # It's the pin, not a boolean client.load_device_by_mnemonic(str(item), pin, passphrase_protection, label, language) else: pin = pin_protection # It's the pin, not a boolean client.load_device_by_xprv(item, pin, passphrase_protection, label, language)
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(":icons/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 __init__(self, parent=None): MyTreeWidget.__init__(self, parent, self.create_menu, [], 2) self.refresh_headers() self.setSelectionMode(QAbstractItemView.ExtendedSelection) self.setSortingEnabled(True) self.show_change = 0 self.show_used = 0 self.change_button = QComboBox(self) self.change_button.currentIndexChanged.connect(self.toggle_change) for t in [_('All'), _('Receiving'), _('Change')]: self.change_button.addItem(t) self.used_button = QComboBox(self) self.used_button.currentIndexChanged.connect(self.toggle_used) for t in [_('All'), _('Unused'), _('Funded'), _('Used')]: self.used_button.addItem(t)
def refresh_headers(self): fx = self.parent.fx if fx and fx.get_fiat_address_config(): ccy = fx.get_currency() else: ccy = _('Fiat') headers = { self.Columns.TYPE: _('Type'), self.Columns.ADDRESS: _('Address'), self.Columns.LABEL: _('Label'), self.Columns.COIN_BALANCE: _('Balance'), self.Columns.FIAT_BALANCE: ccy + ' ' + _('Balance'), self.Columns.NUM_TXS: _('Tx'), } self.update_headers(headers)
def change_homescreen(): from PIL import Image # FIXME dialog = QFileDialog(self, _("Choose Homescreen")) filename, __ = dialog.getOpenFileName() if filename: im = Image.open(str(filename)) if im.size != (hs_cols, hs_rows): raise Exception('Image must be 64 x 128 pixels') im = im.convert('1') pix = im.load() img = '' for j in range(hs_rows): for i in range(hs_cols): img += '1' if pix[i, j] else '0' img = ''.join( chr(int(img[i:i + 8], 2)) for i in range(0, len(img), 8)) invoke_client('change_homescreen', img)
def on_update(self): self.wallet = self.parent.wallet self.network = self.parent.network item = self.currentItem() self.clear() self.utxos = self.wallet.get_utxos() for x in self.utxos: txid = x['prevout_hash'] vout = x['prevout_n'] name_op = self.wallet.transactions[txid].outputs()[vout].name_op if name_op is None: continue # TODO: Support name_new if 'name' in name_op: name = name_op['name'] formatted_name = format_name_identifier(name) value = name_op['value'] formatted_value = format_name_value(value) else: name = None formatted_name = '' value = None formatted_value = '' height = x.get('height') chain_height = self.network.blockchain().height() expires_in = name_expires_in(height, chain_height) formatted_expires_in = '%d' % expires_in if expires_in is not None else '' status = '' if expires_in is not None else _('Update Pending') utxo_item = SortableTreeWidgetItem([ formatted_name, formatted_value, formatted_expires_in, status ]) utxo_item.setFont(0, QFont(MONOSPACE_FONT)) utxo_item.setFont(1, QFont(MONOSPACE_FONT)) utxo_item.setData(0, Qt.UserRole, self.get_name(x)) utxo_item.setData(0, Qt.UserRole + USER_ROLE_NAME, name) utxo_item.setData(0, Qt.UserRole + USER_ROLE_VALUE, value) address = x.get('address') if self.wallet.is_frozen(address): utxo_item.setBackground(0, ColorScheme.BLUE.as_color(True)) self.addChild(utxo_item)
def __init__(self, main_window, exctype, value, tb): BaseCrashReporter.__init__(self, exctype, value, tb) self.main_window = main_window QWidget.__init__(self) self.setWindowTitle('Electrum-NMC - ' + _('An Error Occurred')) self.setMinimumSize(600, 300) main_box = QVBoxLayout() heading = QLabel('<h2>' + BaseCrashReporter.CRASH_TITLE + '</h2>') main_box.addWidget(heading) main_box.addWidget(QLabel(BaseCrashReporter.CRASH_MESSAGE)) main_box.addWidget(QLabel(BaseCrashReporter.REQUEST_HELP_MESSAGE)) collapse_info = QPushButton(_("Show report contents")) collapse_info.clicked.connect( lambda: self.msg_box(QMessageBox.NoIcon, self, _("Report contents"), self.get_report_string(), rich_text=True)) main_box.addWidget(collapse_info) main_box.addWidget(QLabel(BaseCrashReporter.DESCRIBE_ERROR_MESSAGE)) self.description_textfield = QTextEdit() self.description_textfield.setFixedHeight(50) main_box.addWidget(self.description_textfield) main_box.addWidget(QLabel(BaseCrashReporter.ASK_CONFIRM_SEND)) buttons = QHBoxLayout() report_button = QPushButton(_('Send Bug Report')) report_button.clicked.connect(self.send_report) report_button.setIcon(read_QIcon("tab_send.png")) buttons.addWidget(report_button) never_button = QPushButton(_('Never')) never_button.clicked.connect(self.show_never) buttons.addWidget(never_button) close_button = QPushButton(_('Not Now')) close_button.clicked.connect(self.close) buttons.addWidget(close_button) main_box.addLayout(buttons) self.setLayout(main_box) 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) icon = "qrcode_white.png" if ColorScheme.dark_scheme else "qrcode.png" self.addr_e.addButton(icon, self.show_qr, _("Show QR Code")) self.addr_e.setReadOnly(True) vbox.addWidget(self.addr_e) try: pubkeys = self.wallet.get_public_keys(address) except BaseException as e: pubkeys = None if pubkeys: vbox.addWidget(QLabel(_("Public keys") + ':')) for pubkey in pubkeys: pubkey_e = ButtonsLineEdit(pubkey) pubkey_e.addCopyButton(self.app) pubkey_e.setReadOnly(True) vbox.addWidget(pubkey_e) try: redeem_script = self.wallet.pubkeys_to_redeem_script(pubkeys) except BaseException as e: redeem_script = None if redeem_script: vbox.addWidget(QLabel(_("Redeem Script") + ':')) redeem_e = ShowQRTextEdit(text=redeem_script) redeem_e.addCopyButton(self.app) vbox.addWidget(redeem_e) vbox.addWidget(QLabel(_("History"))) addr_hist_model = AddressHistoryModel(self.parent, self.address) self.hw = HistoryList(self.parent, addr_hist_model) addr_hist_model.set_view(self.hw) vbox.addWidget(self.hw) vbox.addLayout(Buttons(CloseButton(self))) self.format_amount = self.parent.format_amount addr_hist_model.refresh('address dialog constructor')