forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathqrimagewidget.cpp
156 lines (132 loc) · 4.89 KB
/
qrimagewidget.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Copyright (c) 2011-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <qt/qrimagewidget.h>
#include <qt/guiutil.h>
#include <QApplication>
#include <QClipboard>
#include <QDrag>
#include <QFontDatabase>
#include <QMenu>
#include <QMimeData>
#include <QMouseEvent>
#include <QPainter>
#if defined(HAVE_CONFIG_H)
#include <config/bitcoin-config.h> /* for USE_QRCODE */
#endif
#ifdef USE_QRCODE
#include <qrencode.h>
#endif
QRImageWidget::QRImageWidget(QWidget *parent):
QLabel(parent), contextMenu(nullptr)
{
contextMenu = new QMenu(this);
contextMenu->addAction(tr("&Save Image…"), this, &QRImageWidget::saveImage);
contextMenu->addAction(tr("&Copy Image"), this, &QRImageWidget::copyImage);
}
bool QRImageWidget::setQR(const QString& data, const QString& text)
{
#ifdef USE_QRCODE
setText("");
if (data.isEmpty()) return false;
// limit length
if (data.length() > MAX_URI_LENGTH) {
setText(tr("Resulting URI too long, try to reduce the text for label / message."));
return false;
}
QRcode *code = QRcode_encodeString(data.toUtf8().constData(), 0, QR_ECLEVEL_L, QR_MODE_8, 1);
if (!code) {
setText(tr("Error encoding URI into QR Code."));
return false;
}
QImage qrImage = QImage(code->width + 6, code->width + 6, QImage::Format_RGB32);
qrImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET));
unsigned char *p = code->data;
for (int y = 0; y < code->width; y++)
{
for (int x = 0; x < code->width; x++)
{
qrImage.setPixel(x + 3, y + 3, ((*p & 1) ? GUIUtil::getThemedQColor(GUIUtil::ThemedColor::QR_PIXEL).rgb() : GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET).rgb()));
p++;
}
}
QRcode_free(code);
// Create the image with respect to the device pixel ratio
int qr_addr_image_width = QR_IMAGE_SIZE;
int qr_addr_image_height = QR_IMAGE_SIZE + QR_IMAGE_MARGIN;
qreal scale = qApp->devicePixelRatio();
QImage qrAddrImage = QImage(qr_addr_image_width * scale, qr_addr_image_height * scale, QImage::Format_RGB32);
qrAddrImage.setDevicePixelRatio(scale);
{
QPainter painter(&qrAddrImage);
// Fill the whole image with border color
qrAddrImage.fill(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BORDER_WIDGET));
// Create a 2px/2px smaller rect and fill it with background color to keep the 1px border with the border color
QRect paddedRect = QRect(1, 1, qr_addr_image_width - 2, qr_addr_image_height - 2);
painter.fillRect(paddedRect, GUIUtil::getThemedQColor(GUIUtil::ThemedColor::BACKGROUND_WIDGET));
painter.drawImage(2, 2, qrImage.scaled(QR_IMAGE_SIZE - 4, QR_IMAGE_SIZE - 4));
if (!text.isEmpty()) {
// calculate ideal font size
QFont font = GUIUtil::getFontNormal();
font.setStretch(QFont::SemiCondensed);
font.setLetterSpacing(QFont::AbsoluteSpacing, 1);
qreal font_size = GUIUtil::calculateIdealFontSize((paddedRect.width() - QR_IMAGE_MARGIN), text, font);
font.setPointSizeF(font_size);
// paint the address
painter.setFont(font);
painter.setPen(GUIUtil::getThemedQColor(GUIUtil::ThemedColor::QR_PIXEL));
paddedRect.setHeight(QR_IMAGE_SIZE + 3);
painter.drawText(paddedRect, Qt::AlignBottom|Qt::AlignCenter, text);
}
painter.end();
}
setPixmap(QPixmap::fromImage(qrAddrImage));
return true;
#else
setText(tr("QR code support not available."));
return false;
#endif
}
QImage QRImageWidget::exportImage()
{
return GUIUtil::GetImage(this);
}
void QRImageWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && GUIUtil::HasPixmap(this)) {
event->accept();
QMimeData *mimeData = new QMimeData;
mimeData->setImageData(exportImage());
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
drag->exec();
} else {
QLabel::mousePressEvent(event);
}
}
void QRImageWidget::saveImage()
{
if (!GUIUtil::HasPixmap(this))
return;
QString fn = GUIUtil::getSaveFileName(
this, tr("Save QR Code"), QString(),
/*: Expanded name of the PNG file format.
See: https://en.wikipedia.org/wiki/Portable_Network_Graphics. */
tr("PNG Image") + QLatin1String(" (*.png)"), nullptr);
if (!fn.isEmpty())
{
exportImage().save(fn);
}
}
void QRImageWidget::copyImage()
{
if (!GUIUtil::HasPixmap(this))
return;
QApplication::clipboard()->setImage(exportImage());
}
void QRImageWidget::contextMenuEvent(QContextMenuEvent *event)
{
if (!GUIUtil::HasPixmap(this))
return;
contextMenu->exec(event->globalPos());
}