qrcodewidget.py (4646B)
1 import qrcode 2 3 from PyQt5.QtGui import QColor, QPen 4 import PyQt5.QtGui as QtGui 5 from PyQt5.QtCore import Qt 6 from PyQt5.QtWidgets import ( 7 QApplication, QVBoxLayout, QTextEdit, QHBoxLayout, QPushButton, QWidget, 8 QFileDialog, 9 ) 10 11 from electrum.i18n import _ 12 from electrum.simple_config import SimpleConfig 13 14 from .util import WindowModalDialog, WWLabel, getSaveFileName 15 16 17 class QRCodeWidget(QWidget): 18 19 def __init__(self, data = None, fixedSize=False): 20 QWidget.__init__(self) 21 self.data = None 22 self.qr = None 23 self.fixedSize=fixedSize 24 if fixedSize: 25 self.setFixedSize(fixedSize, fixedSize) 26 self.setData(data) 27 28 29 def setData(self, data): 30 if self.data != data: 31 self.data = data 32 if self.data: 33 self.qr = qrcode.QRCode( 34 error_correction=qrcode.constants.ERROR_CORRECT_L, 35 box_size=10, 36 border=0, 37 ) 38 self.qr.add_data(self.data) 39 if not self.fixedSize: 40 k = len(self.qr.get_matrix()) 41 self.setMinimumSize(k*5,k*5) 42 else: 43 self.qr = None 44 45 self.update() 46 47 48 def paintEvent(self, e): 49 if not self.data: 50 return 51 52 black = QColor(0, 0, 0, 255) 53 white = QColor(255, 255, 255, 255) 54 black_pen = QPen(black) 55 black_pen.setJoinStyle(Qt.MiterJoin) 56 57 if not self.qr: 58 qp = QtGui.QPainter() 59 qp.begin(self) 60 qp.setBrush(white) 61 qp.setPen(white) 62 r = qp.viewport() 63 qp.drawRect(0, 0, r.width(), r.height()) 64 qp.end() 65 return 66 67 matrix = self.qr.get_matrix() 68 k = len(matrix) 69 qp = QtGui.QPainter() 70 qp.begin(self) 71 r = qp.viewport() 72 73 margin = 10 74 framesize = min(r.width(), r.height()) 75 boxsize = int( (framesize - 2*margin)/k ) 76 size = k*boxsize 77 left = (framesize - size)/2 78 top = (framesize - size)/2 79 # Draw white background with margin 80 qp.setBrush(white) 81 qp.setPen(white) 82 qp.drawRect(0, 0, framesize, framesize) 83 # Draw qr code 84 qp.setBrush(black) 85 qp.setPen(black_pen) 86 for r in range(k): 87 for c in range(k): 88 if matrix[r][c]: 89 qp.drawRect(int(left+c*boxsize), int(top+r*boxsize), 90 boxsize - 1, boxsize - 1) 91 qp.end() 92 93 94 95 class QRDialog(WindowModalDialog): 96 97 def __init__( 98 self, 99 *, 100 data, 101 parent=None, 102 title="", 103 show_text=False, 104 help_text=None, 105 show_copy_text_btn=False, 106 config: SimpleConfig, 107 ): 108 WindowModalDialog.__init__(self, parent, title) 109 self.config = config 110 111 vbox = QVBoxLayout() 112 113 qrw = QRCodeWidget(data) 114 qr_hbox = QHBoxLayout() 115 qr_hbox.addWidget(qrw) 116 qr_hbox.addStretch(1) 117 vbox.addLayout(qr_hbox) 118 119 help_text = data if show_text else help_text 120 if help_text: 121 text_label = WWLabel() 122 text_label.setText(help_text) 123 vbox.addWidget(text_label) 124 hbox = QHBoxLayout() 125 hbox.addStretch(1) 126 127 def print_qr(): 128 filename = getSaveFileName( 129 parent=self, 130 title=_("Select where to save file"), 131 filename="qrcode.png", 132 config=self.config, 133 ) 134 if not filename: 135 return 136 p = qrw.grab() 137 p.save(filename, 'png') 138 self.show_message(_("QR code saved to file") + " " + filename) 139 140 def copy_image_to_clipboard(): 141 p = qrw.grab() 142 QApplication.clipboard().setPixmap(p) 143 self.show_message(_("QR code copied to clipboard")) 144 145 def copy_text_to_clipboard(): 146 QApplication.clipboard().setText(data) 147 self.show_message(_("Text copied to clipboard")) 148 149 b = QPushButton(_("Copy Image")) 150 hbox.addWidget(b) 151 b.clicked.connect(copy_image_to_clipboard) 152 153 if show_copy_text_btn: 154 b = QPushButton(_("Copy Text")) 155 hbox.addWidget(b) 156 b.clicked.connect(copy_text_to_clipboard) 157 158 b = QPushButton(_("Save")) 159 hbox.addWidget(b) 160 b.clicked.connect(print_qr) 161 162 b = QPushButton(_("Close")) 163 hbox.addWidget(b) 164 b.clicked.connect(self.accept) 165 b.setDefault(True) 166 167 vbox.addLayout(hbox) 168 self.setLayout(vbox)