Merge remote-tracking branch 'tobtoht/qr-code-scan' into qr-code-scan

qr-code-scan
mrdeveloper 4 years ago
commit 5ea7959ab2

@ -122,6 +122,11 @@ set(HIDAPI_FOUND OFF)
# QrEncode
find_package(QREncode REQUIRED)
add_definitions(-DWITH_SCANNER)
find_package(ZBar0 REQUIRED)
message(STATUS "libzbar: include dir at ${ZBAR_INCLUDE_DIR}")
message(STATUS "libzbar: libraries at ${ZBAR_LIBRARIES}")
# Tevador 14 word Monero seed
find_package(monero-seed CONFIG)
if(NOT monero-seed_FOUND)

@ -8,13 +8,13 @@ RUN apt install -y gnupg
COPY utils/pubkeys/kitware.asc /kitware.asc
RUN cat /kitware.asc | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
RUN apt install -y automake git pkg-config python wget python3.6-distutils software-properties-common
RUN apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' && apt update
RUN apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' && apt-get update
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Amsterdam
RUN apt install -y build-essential nano vim aptitude ccache libusb-1.0-0-dev tzdata
RUN apt install -y xutils-dev && \
RUN apt-get install -y xutils-dev && \
git clone -b xorgproto-2020.1 --depth 1 https://gitlab.freedesktop.org/xorg/proto/xorgproto && \
cd xorgproto && \
git reset --hard c62e8203402cafafa5ba0357b6d1c019156c9f36 && \
@ -184,14 +184,14 @@ RUN cd /qt-everywhere-src-5.15.0 && \
./configure --prefix=/usr -platform linux-g++-64 -opensource -confirm-license -release -static -no-avx \
-no-opengl -qpa xcb -openssl-linked -I /usr/local/openssl/include -L /usr/local/openssl/lib -system-freetype -fontconfig -glib \
-no-dbus -no-sql-sqlite -no-use-gold-linker -no-kms \
-qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib \
-qt-harfbuzz -qt-libjpeg -qt-libpng -qt-pcre -qt-zlib -gstreamer \
-skip qt3d -skip qtandroidextras -skip qtcanvas3d -skip qtcharts -skip qtconnectivity -skip qtdatavis3d \
-skip qtdoc -skip qtquickcontrols -skip qtquickcontrols2 -skip qtspeech -skip qtgamepad \
-skip qtlocation -skip qtmacextras -skip qtnetworkauth -skip qtpurchasing -optimize-size \
-skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttools \
-skip qtvirtualkeyboard -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebview \
-skip qtwinextras -skip qtx11extras -skip gamepad -skip serialbus -skip location -skip webengine \
-skip qtdeclarative -skip qtmultimedia \
-skip qtdeclarative \
-no-feature-cups -no-feature-ftp -no-feature-pdf -no-feature-animation \
-nomake examples -nomake tests -nomake tools
@ -311,3 +311,11 @@ RUN apt install -y curl && \
echo "24d4f07cf5850f00ab513b228f95769a5a5ed68d35808d98f9959b58d97985a0 xmrig-6.3.5-linux-static-x64.tar.gz" > hashsum.txt && \
sha256sum -c hashsum.txt && \
tar xvf xmrig-6.3.5-linux-static-x64.tar.gz --one-top-level=/xmrig --strip 1
RUN git clone -b stable-0.21 --recursive https://github.com/mchehab/zbar.git && \
cd zbar && \
git reset --hard 505f1a87b32cb7bb0edbaf37e20ccdd46bbae2a3 && \
autoreconf -vfi && \
CFLAGS='-fPIC' CXXFLAGS='-fPIC' ./configure --enable-static --disable-shared --without-imagemagick --with-gtk=no --with-python=no --enable-doc=no && \
make -j$THREADS && \
make install

@ -50,7 +50,7 @@ RUN apt install -y \
RUN git clone -b feather-patch --depth 1 https://git.wownero.com/feather/mxe.git && \
cd mxe && \
make -j$THREADS MXE_TARGETS='x86_64-w64-mingw32.static' gcc libqrencode pkgconf libgpg_error libgcrypt cmake libsodium lzma readline libzmq boost qtbase qtsvg qtwebsockets qtimageformats
make -j$THREADS MXE_TARGETS='x86_64-w64-mingw32.static' gcc libqrencode pkgconf libgpg_error libgcrypt cmake libsodium lzma readline libzmq boost qtbase qtsvg qtwebsockets qtimageformats qtmultimedia
# plugins
RUN cd mxe && make -j$THREADS MXE_PLUGIN_DIRS='/mxe/plugins/apps/' MXE_TARGETS='x86_64-w64-mingw32.static' tor

@ -9,14 +9,30 @@
#
find_package(PkgConfig)
pkg_check_modules(PC_ZBAR QUIET zbar)
set(ZBAR_DEFINITIONS ${PC_ZBAR_CFLAGS_OTHER})
find_library(ZBAR_LIBRARIES NAMES zbar
HINTS ${PC_ZBAR_LIBDIR} ${PC_ZBAR_LIBRARY_DIRS} )
find_path(ZBAR_INCLUDE_DIR Decoder.h
HINTS ${PC_ZBAR_INCLUDEDIR} ${PC_ZBAR_INCLUDE_DIRS}
PATH_SUFFIXES zbar )
if(PkgConfig_FOUND)
pkg_check_modules(PC_ZBAR QUIET zbar)
if(PC_ZBAR_FOUND)
set(ZBAR_DEFINITIONS ${PC_ZBAR_CFLAGS_OTHER})
find_library(ZBAR_LIBRARIES NAMES zbar HINTS ${PC_ZBAR_LIBDIR} ${PC_ZBAR_LIBRARY_DIRS})
find_path(ZBAR_INCLUDE_DIR Decoder.h HINTS ${PC_ZBAR_INCLUDEDIR} ${PC_ZBAR_INCLUDE_DIRS} PATH_SUFFIXES zbar)
endif()
endif()
if(NOT ZBAR_LIBRARIES AND ANDROID)
find_library(ZBARJNI_LIBRARY NAMES zbarjni)
find_library(ICONV_LIBRARY NAMES iconv)
if(ZBARJNI_LIBRARY AND ICONV_LIBRARY)
set(ZBAR_LIBRARIES ${ZBARJNI_LIBRARY} ${ICONV_LIBRARY})
endif()
endif()
if(NOT ZBAR_INCLUDE_DIR)
find_path(ZBAR_H_PATH zbar.h)
if(ZBAR_H_PATH)
set(ZBAR_INCLUDE_DIR "${ZBAR_H_PATH}/zbar")
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ZBAR DEFAULT_MSG ZBAR_LIBRARIES ZBAR_INCLUDE_DIR)
message(STATUS "Found zbar libraries ${ZBAR_LIBRARIES}")
message(STATUS "Found zbar libraries ${ZBAR_LIBRARIES}")

@ -38,6 +38,8 @@ file(GLOB SOURCE_FILES
"wallet/*.cpp"
"qrcode/*.h"
"qrcode/*.cpp"
"qrcode_scanner/*.h"
"qrcode_scanner/*.cpp"
"dialog/*.h"
"dialog/*.cpp"
)
@ -111,6 +113,7 @@ target_include_directories(feather PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/qrcode
${X11_INCLUDE_DIR}
${Boost_INCLUDE_DIRS}
${ZBAR_INCLUDE_DIRS}
${OPENSSL_INCLUDE_DIR}
${Qt5Core_INCLUDE_DIRS}
${Qt5Widgets_INCLUDE_DIRS}
@ -164,6 +167,8 @@ target_compile_definitions(feather
${Qt5Svg_DEFINITIONS}
${Qt5Xml_DEFINITIONS}
${Qt5WebSockets_DEFINITIONS}
${Qt5Multimedia_DEFINITIONS}
${Qt5MultimediaWidgets_DEFINITIONS}
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}")
@ -203,6 +208,7 @@ target_link_libraries(feather
openpgp
Threads::Threads
${QRENCODE_LIBRARY}
${ZBAR_LIBRARIES}
)
if(NOT APPLE)

@ -1,12 +1,9 @@
#include "qrcodescandialog.h"
#include "ui_qrcodescandialog.h"
#include <QClipboard>
#include <QFileDialog>
#include <QMessageBox>
#include <QtMultimedia/QCameraInfo>
#include <QtMultimedia/QCamera>
#include <QCameraImageCapture>
#include <QtMultimedia/QCameraInfo>
QrCodeScanDialog::QrCodeScanDialog(QWidget *parent)
@ -16,20 +13,31 @@ QrCodeScanDialog::QrCodeScanDialog(QWidget *parent)
ui->setupUi(this);
this->setWindowTitle("Scan QR Code");
camera = new QCamera(QCameraInfo::availableCameras().first());
camera->setViewfinder(ui->viewfinder);
camera->start();
auto cameras = QCameraInfo::availableCameras();
if (cameras.count() < 1) {
QMessageBox::warning(parent, "QR code scanner","No available cameras found.");
return;
}
m_camera = new QCamera(cameras.first(), this);
m_camera->setCaptureMode(QCamera::CaptureVideo);
m_camera->setViewfinder(ui->viewfinder);
m_scanner = new QrCodeScanner(this);
m_scanner->setSource(m_camera);
m_scanner->setEnabled(true);
connect(m_scanner, &QrCodeScanner::decoded, this, &QrCodeScanDialog::onDecoded);
m_camera->start();
}
void QrCodeScanDialog::processCapturedImage(int requestId, const QImage& img)
{
qDebug() << "Process image....";
void QrCodeScanDialog::onDecoded(int type, const QString &data) {
decodedString = data;
this->accept();
}
QrCodeScanDialog::~QrCodeScanDialog()
{
camera->stop();
delete camera;
delete m_camera;
delete ui;
}

@ -2,7 +2,7 @@
#define FEATHER_QRCODESCANDIALOG_H
#include <QDialog>
#include <QCamera>
#include "qrcode_scanner/QrCodeScanner.h"
namespace Ui {
class QrCodeScanDialog;
@ -16,12 +16,15 @@ public:
explicit QrCodeScanDialog(QWidget *parent);
~QrCodeScanDialog() override;
QString decodedString = "";
private slots:
void processCapturedImage(int requestId, const QImage &img);
void onDecoded(int type, const QString &data);
private:
Ui::QrCodeScanDialog *ui;
QCamera *camera;
QCamera *m_camera;
QrCodeScanner *m_scanner;
};

@ -0,0 +1,4 @@
file(GLOB_RECURSE SRC_SOURCES *.cpp)
file(GLOB_RECURSE SRC_HEADERS *.h)

@ -0,0 +1,69 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#include "QrCodeScanner.h"
#include <WalletManager.h>
#include <QVideoProbe>
#include <QCamera>
QrCodeScanner::QrCodeScanner(QObject *parent)
: QObject(parent)
, m_processTimerId(-1)
, m_processInterval(750)
, m_enabled(true)
{
m_probe = new QVideoProbe(this);
m_thread = new QrScanThread(this);
m_thread->start();
QObject::connect(m_thread, SIGNAL(decoded(int, QString)), this, SIGNAL(decoded(int, QString)));
QObject::connect(m_thread, SIGNAL(notifyError(const QString &, bool)), this, SIGNAL(notifyError(const QString &, bool)));
connect(m_probe, SIGNAL(videoFrameProbed(const QVideoFrame &)),
this, SLOT(processFrame(const QVideoFrame &)));
}
void QrCodeScanner::setSource(QCamera *camera)
{
m_probe->setSource((QMediaObject *)camera);
}
void QrCodeScanner::processFrame(const QVideoFrame &frame)
{
if(frame.isValid()){
m_curFrame = frame;
}
}
bool QrCodeScanner::enabled() const
{
return m_enabled;
}
void QrCodeScanner::setEnabled(bool enabled)
{
m_enabled = enabled;
if(!enabled && (m_processTimerId != -1) )
{
this->killTimer(m_processTimerId);
m_processTimerId = -1;
}
else if (enabled && (m_processTimerId == -1) )
{
m_processTimerId = this->startTimer(m_processInterval);
}
emit enabledChanged();
}
void QrCodeScanner::timerEvent(QTimerEvent *event)
{
if( (event->timerId() == m_processTimerId) ){
m_thread->addFrame(m_curFrame);
}
}
QrCodeScanner::~QrCodeScanner()
{
m_thread->stop();
m_thread->quit();
if(!m_thread->wait(5000))
{
m_thread->terminate();
m_thread->wait();
}
}

@ -0,0 +1,50 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#ifndef QRCODESCANNER_H_
#define QRCODESCANNER_H_
#include <QImage>
#include <QVideoFrame>
#include "QrScanThread.h"
class QVideoProbe;
class QCamera;
class QrCodeScanner : public QObject
{
Q_OBJECT
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
public:
QrCodeScanner(QObject *parent = Q_NULLPTR);
~QrCodeScanner();
void setSource(QCamera*);
bool enabled() const;
void setEnabled(bool enabled);
public Q_SLOTS:
void processFrame(const QVideoFrame &frame);
Q_SIGNALS:
void enabledChanged();
void decoded(int type, const QString &data);
void decode(int type, const QString &data);
void notifyError(const QString &error, bool warning = false);
protected:
void timerEvent(QTimerEvent *);
QrScanThread *m_thread;
int m_processTimerId;
int m_processInterval;
int m_enabled;
QVideoFrame m_curFrame;
QVideoProbe *m_probe;
};
#endif

@ -0,0 +1,100 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2014-2020, The Monero Project.
#include "QrScanThread.h"
#include <QtGlobal>
#include <QDebug>
QrScanThread::QrScanThread(QObject *parent)
: QThread(parent)
,m_running(true)
{
m_scanner.set_handler(*this);
}
void QrScanThread::image_callback(zbar::Image &image)
{
qDebug() << "image_callback : Found Code ! " ;
for(zbar::Image::SymbolIterator sym = image.symbol_begin();
sym != image.symbol_end();
++sym)
if(!sym->get_count()) {
QString data = QString::fromStdString(sym->get_data());
emit decoded(sym->get_type(), data);
}
}
void QrScanThread::processZImage(zbar::Image &image)
{
m_scanner.recycle_image(image);
zbar::Image tmp = image.convert(*(long*)"Y800");
m_scanner.scan(tmp);
image.set_symbols(tmp.get_symbols());
}
bool QrScanThread::zimageFromQImage(const QImage &qimg, zbar::Image &dst)
{
switch( qimg.format() ){
case QImage::Format_RGB32 :
case QImage::Format_ARGB32 :
case QImage::Format_ARGB32_Premultiplied :
break;
default :
emit notifyError(QString("Invalid QImage Format !"));
return false;
}
unsigned int bpl( qimg.bytesPerLine() ), width( bpl / 4), height( qimg.height());
dst.set_size(width, height);
dst.set_format("BGR4");
unsigned long datalen = qimg.sizeInBytes();
dst.set_data(qimg.bits(), datalen);
if((width * 4 != bpl) || (width * height * 4 > datalen)){
emit notifyError(QString("QImage to Zbar::Image failed !"));
return false;
}
return true;
}
void QrScanThread::processQImage(const QImage &qimg)
{
try {
m_image = QSharedPointer<zbar::Image>(new zbar::Image());
if( ! zimageFromQImage(qimg, *m_image) )
return;
processZImage(*m_image);
}
catch(std::exception &e) {
qDebug() << "ERROR: " << e.what();
emit notifyError(e.what());
}
}
void QrScanThread::processVideoFrame(const QVideoFrame &frame)
{
processQImage(frame.image());
}
void QrScanThread::stop()
{
m_running = false;
m_waitCondition.wakeOne();
}
void QrScanThread::addFrame(const QVideoFrame &frame)
{
QMutexLocker locker(&m_mutex);
m_queue.append(frame);
m_waitCondition.wakeOne();
}
void QrScanThread::run()
{
QVideoFrame frame;
while(m_running) {
QMutexLocker locker(&m_mutex);
while(m_queue.isEmpty() && m_running)
m_waitCondition.wait(&m_mutex);
if(!m_queue.isEmpty())
processVideoFrame(m_queue.takeFirst());
}
}

@ -0,0 +1,44 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020, The Monero Project.
#ifndef _QRSCANTHREAD_H_
#define _QRSCANTHREAD_H_
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QEvent>
#include <QVideoFrame>
#include <QCamera>
#include <zbar.h>
class QrScanThread : public QThread, public zbar::Image::Handler
{
Q_OBJECT
public:
QrScanThread(QObject *parent = Q_NULLPTR);
void addFrame(const QVideoFrame &frame);
virtual void stop();
Q_SIGNALS:
void decoded(int type, const QString &data);
void notifyError(const QString &error, bool warning = false);
protected:
virtual void run();
void processVideoFrame(const QVideoFrame &);
void processQImage(const QImage &);
void processZImage(zbar::Image &image);
virtual void image_callback(zbar::Image &image);
bool zimageFromQImage(const QImage&, zbar::Image &);
private:
zbar::ImageScanner m_scanner;
QSharedPointer<zbar::Image> m_image;
bool m_running;
QMutex m_mutex;
QWaitCondition m_waitCondition;
QList<QVideoFrame> m_queue;
};
#endif

@ -110,11 +110,9 @@ void SendWidget::aliasClicked() {
}
void SendWidget::scanClicked() {
//@TODO handle camera from QtMultimedia eg
// QCamera *camera = new QCamera(QCameraInfo::availableCameras().first());
// camera->start();
auto *dialog = new QrCodeScanDialog(this);
dialog->exec();
ui->lineAddress->setText(dialog->decodedString);
dialog->deleteLater();
}

@ -202,6 +202,10 @@ bool Tor::unpackBins() {
QFile f(torFile);
QFileInfo fileInfo(f);
this->torPath = QDir(this->torDir).filePath(fileInfo.fileName());
#if defined(Q_OS_WIN)
if(!this->torPath.endsWith(".exe"))
this->torPath += ".exe";
#endif
qDebug() << "Writing Tor executable to " << this->torPath;
f.copy(torPath);
f.close();

@ -75,7 +75,7 @@ void XmRig::start(const QString &path,
arguments << "-x" << QString("%1:%2").arg(Tor::torHost).arg(Tor::torPort);
if(tls)
arguments << "--tls";
arguments << "--donate-level" << "1";
QString cmd = QString("%1 %2").arg(path, arguments.join(" "));
emit output(cmd.toUtf8());
m_process.start(path, arguments);
@ -122,13 +122,17 @@ bool XmRig::unpackBins() {
QFile f(rigFile);
QFileInfo fileInfo(f);
this->rigPath = QDir(this->rigDir).filePath(fileInfo.fileName());
#if defined(Q_OS_WIN)
if(!this->rigPath.endsWith(".exe"))
this->rigPath += ".exe";
#endif
qDebug() << "Writing XMRig executable to " << this->rigPath;
f.copy(rigPath);
f.close();
#if defined(Q_OS_UNIX)
QFile torBin(this->rigPath);
torBin.setPermissions(QFile::ExeGroup | QFile::ExeOther | QFile::ExeOther | QFile::ExeUser);
QFile rigBin(this->rigPath);
rigBin.setPermissions(QFile::ExeGroup | QFile::ExeOther | QFile::ExeOther | QFile::ExeUser);
#endif
return true;
}

Loading…
Cancel
Save