electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit d2cad7bbbbfa1b6b175ec39de36a76453192137d
parent f5a76f7dcf152c523933a60d4d41330f7e7dd7c0
Author: ThomasV <thomasv@gitorious>
Date:   Sat, 14 Jun 2014 12:17:44 +0200

new widget: QRTextEdit

Diffstat:
Mgui/qt/main_window.py | 45+++++----------------------------------------
Mgui/qt/paytoedit.py | 14++++++++++----
Mgui/qt/qrcodewidget.py | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Agui/qt/qrtextedit.py | 43+++++++++++++++++++++++++++++++++++++++++++
Mgui/qt/seed_dialog.py | 7++++---
Mgui/qt/util.py | 3++-
Micons.qrc | 1+
Aicons/qrcode.png | 0
Mplugins/qrscanner.py | 13+++++++------
9 files changed, 125 insertions(+), 54 deletions(-)

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py @@ -45,7 +45,7 @@ from electrum import bmp, pyqrnative from amountedit import AmountEdit, BTCAmountEdit, MyLineEdit from network_dialog import NetworkDialog -from qrcodewidget import QRCodeWidget +from qrcodewidget import QRCodeWidget, QRDialog from decimal import Decimal @@ -664,7 +664,7 @@ class ElectrumWindow(QMainWindow): from paytoedit import PayToEdit self.amount_e = BTCAmountEdit(self.get_decimal_point) - self.payto_e = PayToEdit(self.amount_e) + self.payto_e = PayToEdit(self) self.payto_help = HelpButton(_('Recipient of the funds.') + '\n\n' + _('You may enter a Bitcoin address, a label from your list of contacts (a list of completions will be proposed), or an alias (email-like address that forwards to a Bitcoin address)')) grid.addWidget(QLabel(_('Pay to')), 1, 0) grid.addWidget(self.payto_e, 1, 1, 1, 3) @@ -1669,44 +1669,9 @@ class ElectrumWindow(QMainWindow): def show_qrcode(self, data, title = _("QR code")): - if not data: return - d = QDialog(self) - d.setModal(1) - d.setWindowTitle(title) - d.setMinimumSize(270, 300) - vbox = QVBoxLayout() - qrw = QRCodeWidget(data) - vbox.addWidget(qrw, 1) - vbox.addWidget(QLabel(data), 0, Qt.AlignHCenter) - hbox = QHBoxLayout() - hbox.addStretch(1) - - filename = os.path.join(self.config.path, "qrcode.bmp") - - def print_qr(): - bmp.save_qrcode(qrw.qr, filename) - QMessageBox.information(None, _('Message'), _("QR code saved to file") + " " + filename, _('OK')) - - def copy_to_clipboard(): - bmp.save_qrcode(qrw.qr, filename) - self.app.clipboard().setImage(QImage(filename)) - QMessageBox.information(None, _('Message'), _("QR code saved to clipboard"), _('OK')) - - b = QPushButton(_("Copy")) - hbox.addWidget(b) - b.clicked.connect(copy_to_clipboard) - - b = QPushButton(_("Save")) - hbox.addWidget(b) - b.clicked.connect(print_qr) - - b = QPushButton(_("Close")) - hbox.addWidget(b) - b.clicked.connect(d.accept) - b.setDefault(True) - - vbox.addLayout(hbox) - d.setLayout(vbox) + if not data: + return + d = QRDialog(data, self, title) d.exec_() diff --git a/gui/qt/paytoedit.py b/gui/qt/paytoedit.py @@ -18,6 +18,7 @@ from PyQt4.QtCore import * from PyQt4.QtGui import * +from qrtextedit import QRTextEdit import re from decimal import Decimal @@ -29,11 +30,12 @@ RE_ALIAS = '(.*?)\s*\<([1-9A-HJ-NP-Za-km-z]{26,})\>' frozen_style = "QWidget { background-color:none; border:none;}" normal_style = "QTextEdit { }" -class PayToEdit(QTextEdit): +class PayToEdit(QRTextEdit): - def __init__(self, amount_edit): - QTextEdit.__init__(self) - self.amount_edit = amount_edit + def __init__(self, win): + QRTextEdit.__init__(self) + self.win = win + self.amount_edit = win.amount_e self.document().contentsChanged.connect(self.update_size) self.heightMin = 0 self.heightMax = 150 @@ -44,6 +46,10 @@ class PayToEdit(QTextEdit): self.outputs = [] self.is_pr = False + def qr_input(self): + from electrum.plugins import run_hook + run_hook('scan_qr_hook', lambda x: self.win.pay_from_URI(x)) + def lock_amount(self): self.amount_edit.setFrozen(True) diff --git a/gui/qt/qrcodewidget.py b/gui/qt/qrcodewidget.py @@ -82,3 +82,56 @@ class QRCodeWidget(QWidget): qp.drawRect(left+c*boxsize, top+r*boxsize, boxsize, boxsize) qp.end() + +import os +from electrum.i18n import _ + +class QRDialog(QDialog): + + def __init__(self, data, parent=None, title = "", show_text=False): + QDialog.__init__(self, parent) + + d = self + d.setModal(1) + d.setWindowTitle(title) + d.setMinimumSize(270, 300) + vbox = QVBoxLayout() + qrw = QRCodeWidget(data) + vbox.addWidget(qrw, 1) + if show_text: + text = QTextEdit() + text.setText(data) + text.setReadOnly(True) + vbox.addWidget(text) + hbox = QHBoxLayout() + hbox.addStretch(1) + + if parent: + self.config = parent.config + filename = os.path.join(self.config.path, "qrcode.bmp") + + def print_qr(): + bmp.save_qrcode(qrw.qr, filename) + QMessageBox.information(None, _('Message'), _("QR code saved to file") + " " + filename, _('OK')) + + def copy_to_clipboard(): + bmp.save_qrcode(qrw.qr, filename) + self.parent().app.clipboard().setImage(QImage(filename)) + QMessageBox.information(None, _('Message'), _("QR code saved to clipboard"), _('OK')) + + b = QPushButton(_("Copy")) + hbox.addWidget(b) + b.clicked.connect(copy_to_clipboard) + + b = QPushButton(_("Save")) + hbox.addWidget(b) + b.clicked.connect(print_qr) + + b = QPushButton(_("Close")) + hbox.addWidget(b) + b.clicked.connect(d.accept) + b.setDefault(True) + + vbox.addLayout(hbox) + d.setLayout(vbox) + diff --git a/gui/qt/qrtextedit.py b/gui/qt/qrtextedit.py @@ -0,0 +1,43 @@ +from electrum.i18n import _ +from PyQt4.QtGui import * +from PyQt4.QtCore import * + +class QRTextEdit(QTextEdit): + + def __init__(self): + QTextEdit.__init__(self) + self.button = QToolButton(self) + self.button.setIcon(QIcon(":icons/qrcode.png")) + self.button.setStyleSheet("QToolButton { border: none; padding: 0px; }") + self.button.setVisible(True) + self.button.clicked.connect(lambda: self.qr_show() if self.isReadOnly() else self.qr_input()) + #frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) + #self.setStyleSheet(QString("QLineEdit { padding-right: %1px; } ").arg(self.button.sizeHint().width() + frameWidth + 1)) + #msz = self.minimumSizeHint() + #self.setMinimumSize(max(msz.width(), self.button.sizeHint().height() + frameWidth * 2 + 2), + # max(msz.height(), self.button.sizeHint().height() + frameWidth * 2 + 2)) + + def resizeEvent(self, e): + o = QTextEdit.resizeEvent(self, e) + sz = self.button.sizeHint() + frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) + self.button.move(self.rect().right() - frameWidth - sz.width(), + (self.rect().bottom() - frameWidth - sz.height())) + return o + + def contextMenuEvent(self, e): + m = self.createStandardContextMenu() + if self.isReadOnly(): + m.addAction(_("Show as QR code"), self.qr_show) + else: + m.addAction(_("Read QR code"), self.qr_input) + m.exec_(e.globalPos()) + + def qr_show(self): + from qrcodewidget import QRDialog + QRDialog(str(self.toPlainText())).exec_() + + def qr_input(self): + from electrum.plugins import run_hook + run_hook('scan_qr_hook', self.setText) + diff --git a/gui/qt/seed_dialog.py b/gui/qt/seed_dialog.py @@ -21,8 +21,9 @@ from PyQt4.QtCore import * import PyQt4.QtCore as QtCore from electrum.i18n import _ from electrum import mnemonic -from qrcodewidget import QRCodeWidget +from qrcodewidget import QRCodeWidget, QRDialog from util import close_button +from qrtextedit import QRTextEdit class SeedDialog(QDialog): def __init__(self, parent, seed, imported_keys): @@ -70,7 +71,7 @@ def show_seed_box(seed, sid=None): + _("If you ever need to recover your wallet from seed, you will need both this seed and your cold seed.") + " " \ label1 = QLabel(msg+ ":") - seed_text = QTextEdit(seed) + seed_text = QRTextEdit(seed) seed_text.setReadOnly(True) seed_text.setMaximumHeight(130) @@ -106,7 +107,7 @@ def enter_seed_box(msg, sid=None): label = QLabel(msg) label.setWordWrap(True) - seed_e = QTextEdit() + seed_e = QRTextEdit() seed_e.setMaximumHeight(100) seed_e.setTabChangesFocus(True) diff --git a/gui/qt/util.py b/gui/qt/util.py @@ -98,6 +98,7 @@ def ok_cancel_buttons(dialog, ok_label=_("OK") ): return hbox def text_dialog(parent, title, label, ok_label, default=None): + from qrtextedit import QRTextEdit dialog = QDialog(parent) dialog.setMinimumWidth(500) dialog.setWindowTitle(title) @@ -105,7 +106,7 @@ def text_dialog(parent, title, label, ok_label, default=None): l = QVBoxLayout() dialog.setLayout(l) l.addWidget(QLabel(label)) - txt = QTextEdit() + txt = QRTextEdit() if default: txt.setText(default) l.addWidget(txt) diff --git a/icons.qrc b/icons.qrc @@ -24,5 +24,6 @@ <file>icons/unconfirmed.png</file> <file>icons/network.png</file> <file>icons/dark_background.png</file> + <file>icons/qrcode.png</file> </qresource> </RCC> diff --git a/icons/qrcode.png b/icons/qrcode.png Binary files differ. diff --git a/plugins/qrscanner.py b/plugins/qrscanner.py @@ -45,11 +45,6 @@ class Plugin(BasePlugin): def init(self): self.win = self.gui.main_window self.win.raw_transaction_menu.addAction(_("&From QR code"), self.read_raw_qr) - b = QPushButton(_("Scan QR code")) - b.clicked.connect(lambda: self.win.pay_from_URI(self.scan_qr())) - self.win.send_grid.addWidget(b, 1, 5) - self.win.send_grid.setColumnStretch(5, 0) - self.win.send_grid.setColumnStretch(6, 1) def init_transaction_dialog(self, dialog, buttons): b = QPushButton(_("Show QR code")) @@ -59,6 +54,12 @@ class Plugin(BasePlugin): def is_available(self): return self._is_available + def scan_qr_hook(self, func): + data = self.scan_qr() + if type(data) != str: + return + func(data) + def scan_qr(self): proc = zbar.Processor() try: @@ -84,7 +85,7 @@ class Plugin(BasePlugin): def show_raw_qr(self, tx): try: json_text = json.dumps(tx.as_dict()).replace(' ', '') - self.win.show_qrcode(json_text, 'Unsigned Transaction') + self.win.show_qrcode(json_text, 'Transaction') except Exception as e: self.win.show_message(str(e))