2015-06-06 09:40:08 +08:00
|
|
|
/*
|
|
|
|
Copyright © 2015 by The qTox Project
|
|
|
|
|
|
|
|
This file is part of qTox, a Qt-based graphical interface for Tox.
|
|
|
|
|
|
|
|
qTox is libre software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
qTox is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2015-03-07 20:40:45 +08:00
|
|
|
#include "qrwidget.h"
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <QBuffer>
|
|
|
|
#include <QImage>
|
2015-03-17 03:53:35 +08:00
|
|
|
#include <qrencode.h>
|
2015-03-20 05:13:56 +08:00
|
|
|
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
#include <errno.h>
|
|
|
|
#else
|
|
|
|
#include <sys/errno.h>
|
|
|
|
#endif
|
2015-03-07 20:40:45 +08:00
|
|
|
|
|
|
|
QRWidget::QRWidget(QWidget *parent) : QWidget(parent), data("0")
|
2015-03-08 04:29:39 +08:00
|
|
|
//Note: The encoding fails with empty string so I just default to something else.
|
|
|
|
//Use the setQRData() call to change this.
|
2015-03-07 20:40:45 +08:00
|
|
|
{
|
|
|
|
//size of the qimage might be problematic in the future, but it works for me
|
|
|
|
size.setWidth(480);
|
|
|
|
size.setHeight(480);
|
|
|
|
image = new QImage(size, QImage::Format_RGB32);
|
|
|
|
}
|
|
|
|
|
2015-05-10 04:35:58 +08:00
|
|
|
QRWidget::~QRWidget()
|
|
|
|
{
|
|
|
|
delete image;
|
|
|
|
}
|
|
|
|
|
2015-03-17 03:53:35 +08:00
|
|
|
void QRWidget::setQRData(const QString& data)
|
2015-03-07 20:40:45 +08:00
|
|
|
{
|
2015-03-17 03:53:35 +08:00
|
|
|
this->data = data;
|
2015-03-08 22:20:15 +08:00
|
|
|
paintImage();
|
|
|
|
}
|
|
|
|
|
|
|
|
QImage* QRWidget::getImage()
|
|
|
|
{
|
|
|
|
return image;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief QRWidget::saveImage
|
|
|
|
* @param path Full path to the file with extension.
|
|
|
|
* @return indicate if saving was successful.
|
|
|
|
*/
|
|
|
|
bool QRWidget::saveImage(QString path)
|
|
|
|
{
|
|
|
|
return image->save(path, 0, 75); //0 - image format same as file extension, 75-quality, png file is ~6.3kb
|
2015-03-07 20:40:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//http://stackoverflow.com/questions/21400254/how-to-draw-a-qr-code-with-qt-in-native-c-c
|
|
|
|
void QRWidget::paintImage()
|
|
|
|
{
|
|
|
|
QPainter painter(image);
|
|
|
|
//NOTE: I have hardcoded some parameters here that would make more sense as variables.
|
2015-03-08 04:29:39 +08:00
|
|
|
// ECLEVEL_M is much faster recognizable by barcodescanner any any other type
|
2015-03-17 03:53:35 +08:00
|
|
|
// https://fukuchi.org/works/qrencode/manual/qrencode_8h.html#a4cebc3c670efe1b8866b14c42737fc8f
|
|
|
|
// any mode other than QR_MODE_8 or QR_MODE_KANJI results in EINVAL. First 1 is version, second is case sensitivity
|
|
|
|
QRcode* qr = QRcode_encodeString(data.toStdString().c_str(), 1, QR_ECLEVEL_M, QR_MODE_8, 1);
|
|
|
|
|
|
|
|
if (qr != nullptr)
|
2015-03-07 20:40:45 +08:00
|
|
|
{
|
|
|
|
QColor fg("black");
|
|
|
|
QColor bg("white");
|
|
|
|
painter.setBrush(bg);
|
|
|
|
painter.setPen(Qt::NoPen);
|
|
|
|
painter.drawRect(0, 0, size.width(), size.height());
|
|
|
|
painter.setBrush(fg);
|
2015-03-08 04:29:39 +08:00
|
|
|
const int s = qr->width > 0 ? qr->width : 1;
|
2015-03-07 20:40:45 +08:00
|
|
|
const double w = width();
|
|
|
|
const double h = height();
|
|
|
|
const double aspect = w / h;
|
|
|
|
const double scale = ((aspect > 1.0) ? h : w) / s;
|
2015-03-17 03:53:35 +08:00
|
|
|
|
|
|
|
for (int y = 0; y < s; y++)
|
2015-03-07 20:40:45 +08:00
|
|
|
{
|
|
|
|
const int yy = y * s;
|
2015-03-17 03:53:35 +08:00
|
|
|
for (int x = 0; x < s; x++)
|
2015-03-07 20:40:45 +08:00
|
|
|
{
|
|
|
|
const int xx = yy + x;
|
|
|
|
const unsigned char b = qr->data[xx];
|
2015-03-17 03:53:35 +08:00
|
|
|
if (b & 0x01)
|
2015-03-07 20:40:45 +08:00
|
|
|
{
|
|
|
|
const double rx1 = x * scale,
|
|
|
|
ry1 = y * scale;
|
|
|
|
QRectF r(rx1, ry1, scale, scale);
|
|
|
|
painter.drawRects(&r, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QRcode_free(qr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QColor error("red");
|
|
|
|
painter.setBrush(error);
|
|
|
|
painter.drawRect(0, 0, width(), height());
|
|
|
|
qDebug() << "QR FAIL: " << strerror(errno);
|
|
|
|
}
|
2015-03-17 03:53:35 +08:00
|
|
|
|
|
|
|
qr = nullptr;
|
2015-03-07 20:40:45 +08:00
|
|
|
}
|