Bitcoin ABC  0.29.2
P2P Digital Currency
qrimagewidget.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2018 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <qt/qrimagewidget.h>
6 
7 #include <qt/guiutil.h>
8 
9 #include <QApplication>
10 #include <QClipboard>
11 #include <QDrag>
12 #include <QMenu>
13 #include <QMimeData>
14 #include <QMouseEvent>
15 #include <QPainter>
16 
17 #if defined(HAVE_CONFIG_H)
18 #include <config/bitcoin-config.h> /* for USE_QRCODE */
19 #endif
20 
21 #ifdef USE_QRCODE
22 #include <qrencode.h>
23 #endif
24 
26  : QLabel(parent), contextMenu(nullptr) {
27  contextMenu = new QMenu(this);
28  QAction *saveImageAction = new QAction(tr("&Save Image..."), this);
29  connect(saveImageAction, &QAction::triggered, this,
31  contextMenu->addAction(saveImageAction);
32  QAction *copyImageAction = new QAction(tr("&Copy Image"), this);
33  connect(copyImageAction, &QAction::triggered, this,
35  contextMenu->addAction(copyImageAction);
36 }
37 
39 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
40  return !pixmap(Qt::ReturnByValue).isNull();
41 #else
42  return pixmap() != nullptr;
43 #endif
44 }
45 
46 bool QRImageWidget::setQR(const QString &qrData, const QString &text) {
47 #ifdef USE_QRCODE
48  setText("");
49  if (qrData.isEmpty()) {
50  return false;
51  }
52 
53  // limit length
54  if (qrData.length() > MAX_URI_LENGTH) {
55  setText(tr("Resulting URI too long, try to reduce the text for label / "
56  "message."));
57  return false;
58  }
59 
60  QRcode *code = QRcode_encodeString(qrData.toUtf8().constData(), 0,
61  QR_ECLEVEL_L, QR_MODE_8, 1);
62 
63  if (!code) {
64  setText(tr("Error encoding URI into QR Code."));
65  return false;
66  }
67 
68  QImage qrImage =
69  QImage(code->width + 8, code->width + 8, QImage::Format_RGB32);
70  qrImage.fill(0xffffff);
71  uint8_t *p = code->data;
72  for (int y = 0; y < code->width; ++y) {
73  for (int x = 0; x < code->width; ++x) {
74  qrImage.setPixel(x + 4, y + 4, ((*p & 1) ? 0x0 : 0xffffff));
75  ++p;
76  }
77  }
78  QRcode_free(code);
79 
80  QImage qrAddrImage =
81  QImage(QR_IMAGE_SIZE, QR_IMAGE_SIZE + (text.isEmpty() ? 0 : 20),
82  QImage::Format_RGB32);
83  qrAddrImage.fill(0xffffff);
84  QPainter painter(&qrAddrImage);
85  painter.drawImage(0, 0, qrImage.scaled(QR_IMAGE_SIZE, QR_IMAGE_SIZE));
86 
87  if (!text.isEmpty()) {
88  QFont font = GUIUtil::fixedPitchFont();
89  QRect paddedRect = qrAddrImage.rect();
90 
91  // calculate ideal font size
92  qreal font_size = GUIUtil::calculateIdealFontSize(
93  paddedRect.width() - 20, text, font);
94  font.setPointSizeF(font_size);
95 
96  painter.setFont(font);
97  paddedRect.setHeight(QR_IMAGE_SIZE + 12);
98  painter.drawText(paddedRect, Qt::AlignBottom | Qt::AlignCenter, text);
99  }
100 
101  painter.end();
102  setPixmap(QPixmap::fromImage(qrAddrImage));
103 
104  return true;
105 #else
106  setText(tr("QR code support not available."));
107  return false;
108 #endif
109 }
110 
112 #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
113  return pixmap(Qt::ReturnByValue).toImage();
114 #else
115  return hasPixmap() ? pixmap()->toImage() : QImage();
116 #endif
117 }
118 
119 void QRImageWidget::mousePressEvent(QMouseEvent *event) {
120  if (event->button() == Qt::LeftButton && hasPixmap()) {
121  event->accept();
122  QMimeData *mimeData = new QMimeData;
123  mimeData->setImageData(exportImage());
124 
125  QDrag *drag = new QDrag(this);
126  drag->setMimeData(mimeData);
127  drag->exec();
128  } else {
129  QLabel::mousePressEvent(event);
130  }
131 }
132 
134  if (!hasPixmap()) {
135  return;
136  }
137  QString fn = GUIUtil::getSaveFileName(this, tr("Save QR Code"), QString(),
138  tr("PNG Image (*.png)"), nullptr);
139  if (!fn.isEmpty()) {
140  exportImage().save(fn);
141  }
142 }
143 
145  if (!hasPixmap()) {
146  return;
147  }
148  QApplication::clipboard()->setImage(exportImage());
149 }
150 
151 void QRImageWidget::contextMenuEvent(QContextMenuEvent *event) {
152  if (!hasPixmap()) {
153  return;
154  }
155  contextMenu->exec(event->globalPos());
156 }
bool setQR(const QString &qrData, const QString &text="")
QMenu * contextMenu
Definition: qrimagewidget.h:43
bool hasPixmap() const
QImage exportImage()
virtual void contextMenuEvent(QContextMenuEvent *event) override
virtual void mousePressEvent(QMouseEvent *event) override
QRImageWidget(QWidget *parent=nullptr)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedSuffixOut)
Get save filename, mimics QFileDialog::getSaveFileName, except that it appends a default suffix when ...
Definition: guiutil.cpp:291
QFont fixedPitchFont()
Definition: guiutil.cpp:84
qreal calculateIdealFontSize(int width, const QString &text, QFont font, qreal minPointSize, qreal font_size)
Definition: guiutil.cpp:913
static const int QR_IMAGE_SIZE
Definition: qrimagewidget.h:15
static const int MAX_URI_LENGTH
Definition: qrimagewidget.h:12