/ src / plugins / menu_qrcode.py
menu_qrcode.py
  1  # -*- coding: utf-8 -*-
  2  """
  3  A menu plugin showing QR-Code for bitmessage address in modal dialog.
  4  """
  5  
  6  import urllib.request, urllib.parse, urllib.error
  7  
  8  import qrcode
  9  from PyQt4 import QtCore, QtGui
 10  
 11  from pybitmessage.tr import _translate
 12  
 13  
 14  # http://stackoverflow.com/questions/20452486
 15  class Image(qrcode.image.base.BaseImage):  # pylint: disable=abstract-method
 16      """Image output class for qrcode using QPainter"""
 17  
 18      def __init__(self, border, width, box_size):
 19          # pylint: disable=super-init-not-called
 20          self.border = border
 21          self.width = width
 22          self.box_size = box_size
 23          size = (width + border * 2) * box_size
 24          self._image = QtGui.QImage(
 25              size, size, QtGui.QImage.Format_RGB16)
 26          self._image.fill(QtCore.Qt.white)
 27  
 28      def pixmap(self):
 29          """Get image pixmap"""
 30          return QtGui.QPixmap.fromImage(self._image)
 31  
 32      def drawrect(self, row, col):
 33          """Draw a single rectangle - implementation"""
 34          painter = QtGui.QPainter(self._image)
 35          painter.fillRect(
 36              (col + self.border) * self.box_size,
 37              (row + self.border) * self.box_size,
 38              self.box_size, self.box_size,
 39              QtCore.Qt.black)
 40  
 41  
 42  class QRCodeDialog(QtGui.QDialog):
 43      """The dialog"""
 44      def __init__(self, parent):
 45          super(QRCodeDialog, self).__init__(parent)
 46          self.image = QtGui.QLabel(self)
 47          self.label = QtGui.QLabel(self)
 48          font = QtGui.QFont()
 49          font.setBold(True)
 50          font.setWeight(75)
 51          self.label.setFont(font)
 52          self.label.setAlignment(
 53              QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 54          buttonBox = QtGui.QDialogButtonBox(self)
 55          buttonBox.setOrientation(QtCore.Qt.Horizontal)
 56          buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok)
 57          buttonBox.accepted.connect(self.accept)
 58          layout = QtGui.QVBoxLayout(self)
 59          layout.addWidget(self.image)
 60          layout.addWidget(self.label)
 61          layout.addWidget(buttonBox)
 62          self.retranslateUi()
 63  
 64      def retranslateUi(self):
 65          """A conventional Qt Designer method for dynamic l10n"""
 66          self.setWindowTitle(_translate("QRCodeDialog", "QR-code"))
 67  
 68      def render(self, text):
 69          """Draw QR-code and address in labels"""
 70          pixmap = qrcode.make(text, image_factory=Image).pixmap()
 71          self.image.setPixmap(pixmap)
 72          self.label.setText(text)
 73          self.label.setToolTip(text)
 74          self.label.setFixedWidth(pixmap.width())
 75          self.setFixedSize(QtGui.QWidget.sizeHint(self))
 76  
 77  
 78  def connect_plugin(form):
 79      """Plugin entry point"""
 80      def on_action_ShowQR():
 81          """A slot for popup menu action"""
 82          try:
 83              dialog = form.qrcode_dialog
 84          except AttributeError:
 85              form.qrcode_dialog = dialog = QRCodeDialog(form)
 86          account = form.getContactSelected()
 87          try:
 88              label = account._getLabel()  # pylint: disable=protected-access
 89          except AttributeError:
 90              try:
 91                  label = account.getLabel()
 92              except AttributeError:
 93                  return
 94          dialog.render(
 95              'bitmessage:%s' % account.address + (
 96                  '?' + urllib.parse.urlencode({'label': label.encode('utf-8')})
 97                  if label != account.address else '')
 98          )
 99          dialog.exec_()
100  
101      return on_action_ShowQR, _translate("MainWindow", "Show QR-code")