mirror of
https://github.com/monero-project/monero-gui.git
synced 2025-01-23 11:15:00 +00:00
commit
6c8e770a61
13 changed files with 627 additions and 14 deletions
|
@ -85,15 +85,15 @@ Packaging for your favorite distribution would be a welcome contribution!
|
||||||
|
|
||||||
- For Ubuntu 16.04 i386
|
- For Ubuntu 16.04 i386
|
||||||
|
|
||||||
`sudo apt-get install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-xmllistmodel qttools5-dev-tools qml-module-qtquick-dialogs`
|
`sudo apt-get install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-xmllistmodel qttools5-dev-tools qml-module-qtquick-dialogs libzbar-dev`
|
||||||
|
|
||||||
- For Ubuntu 16.04 x64
|
- For Ubuntu 16.04 x64
|
||||||
|
|
||||||
`sudo apt-get install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-xmllistmodel qttools5-dev-tools qml-module-qtquick-dialogs qml-module-qt-labs-settings libqt5qml-graphicaleffects`
|
`sudo apt-get install qtbase5-dev qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtquick-xmllistmodel qttools5-dev-tools qml-module-qtquick-dialogs qml-module-qt-labs-settings libqt5qml-graphicaleffects libzbar-dev`
|
||||||
|
|
||||||
- For Linux Mint 18 "Sarah" - Cinnamon (64-bit)
|
- For Linux Mint 18 "Sarah" - Cinnamon (64-bit)
|
||||||
|
|
||||||
`sudo apt install qml-module-qt-labs-settings qml-module-qtgraphicaleffects`
|
`sudo apt install qml-module-qt-labs-settings qml-module-qtgraphicaleffects libzbar-dev`
|
||||||
|
|
||||||
6. Build the GUI.
|
6. Build the GUI.
|
||||||
|
|
||||||
|
|
4
build.sh
4
build.sh
|
@ -24,12 +24,12 @@ elif [ "$BUILD_TYPE" == "release-static" ]; then
|
||||||
BIN_PATH=release/bin
|
BIN_PATH=release/bin
|
||||||
elif [ "$BUILD_TYPE" == "release-android" ]; then
|
elif [ "$BUILD_TYPE" == "release-android" ]; then
|
||||||
echo "Building release for ANDROID"
|
echo "Building release for ANDROID"
|
||||||
CONFIG="CONFIG+=release static";
|
CONFIG="CONFIG+=release static WITH_SCANNER";
|
||||||
ANDROID=true
|
ANDROID=true
|
||||||
BIN_PATH=release/bin
|
BIN_PATH=release/bin
|
||||||
elif [ "$BUILD_TYPE" == "debug-android" ]; then
|
elif [ "$BUILD_TYPE" == "debug-android" ]; then
|
||||||
echo "Building debug for ANDROID : ultra INSECURE !!"
|
echo "Building debug for ANDROID : ultra INSECURE !!"
|
||||||
CONFIG="CONFIG+=debug qml_debug";
|
CONFIG="CONFIG+=debug qml_debug WITH_SCANNER";
|
||||||
ANDROID=true
|
ANDROID=true
|
||||||
BIN_PATH=debug/bin
|
BIN_PATH=debug/bin
|
||||||
elif [ "$BUILD_TYPE" == "debug" ]; then
|
elif [ "$BUILD_TYPE" == "debug" ]; then
|
||||||
|
|
134
components/QRCodeScanner.qml
Normal file
134
components/QRCodeScanner.qml
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
// Copyright (c) 2014-2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtMultimedia 5.4
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import moneroComponents.QRCodeScanner 1.0
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id : root
|
||||||
|
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
z: parent.z+1
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
visible: false
|
||||||
|
color: "black"
|
||||||
|
state: "Stopped"
|
||||||
|
|
||||||
|
signal qrcode_decoded(string address, string payment_id, string amount, string tx_description, string recipient_name)
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "Capture"
|
||||||
|
StateChangeScript {
|
||||||
|
script: {
|
||||||
|
root.visible = true
|
||||||
|
camera.captureMode = Camera.CaptureStillImage
|
||||||
|
camera.start()
|
||||||
|
finder.enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "Stopped"
|
||||||
|
StateChangeScript {
|
||||||
|
script: {
|
||||||
|
camera.stop()
|
||||||
|
root.visible = false
|
||||||
|
finder.enabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Camera {
|
||||||
|
id: camera
|
||||||
|
objectName: "qrCameraQML"
|
||||||
|
captureMode: Camera.CaptureStillImage
|
||||||
|
|
||||||
|
focus {
|
||||||
|
focusMode: Camera.FocusContinuous
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QRCodeScanner {
|
||||||
|
id : finder
|
||||||
|
objectName: "QrFinder"
|
||||||
|
onDecoded : {
|
||||||
|
root.qrcode_decoded(address, payment_id, amount, tx_description, recipient_name)
|
||||||
|
root.state = "Stopped"
|
||||||
|
}
|
||||||
|
onNotifyError : {
|
||||||
|
if( warning )
|
||||||
|
messageDialog.icon = StandardIcon.Critical
|
||||||
|
else {
|
||||||
|
messageDialog.icon = StandardIcon.Warning
|
||||||
|
root.state = "Stopped"
|
||||||
|
}
|
||||||
|
messageDialog.text = error
|
||||||
|
messageDialog.visible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoOutput {
|
||||||
|
id: viewfinder
|
||||||
|
visible: root.state == "Capture"
|
||||||
|
|
||||||
|
x: 0
|
||||||
|
y: 0
|
||||||
|
z: parent.z+1
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
|
||||||
|
source: camera
|
||||||
|
autoOrientation: true
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
propagateComposedEvents: true
|
||||||
|
onPressAndHold: {
|
||||||
|
if (camera.lockStatus == Camera.locked)camera.unlock()
|
||||||
|
camera.searchAndLock()
|
||||||
|
}
|
||||||
|
onDoubleClicked: {
|
||||||
|
root.state = "Stopped"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageDialog {
|
||||||
|
id: messageDialog
|
||||||
|
title: "Scanning QrCode"
|
||||||
|
onAccepted: {
|
||||||
|
root.state = "Stopped"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
main.cpp
13
main.cpp
|
@ -39,6 +39,7 @@
|
||||||
#include "WalletManager.h"
|
#include "WalletManager.h"
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
#include "QRCodeImageProvider.h"
|
#include "QRCodeImageProvider.h"
|
||||||
|
#include "QrCodeScanner.h"
|
||||||
#include "PendingTransaction.h"
|
#include "PendingTransaction.h"
|
||||||
#include "UnsignedTransaction.h"
|
#include "UnsignedTransaction.h"
|
||||||
#include "TranslationManager.h"
|
#include "TranslationManager.h"
|
||||||
|
@ -109,6 +110,8 @@ int main(int argc, char *argv[])
|
||||||
qRegisterMetaType<TransactionInfo::Direction>();
|
qRegisterMetaType<TransactionInfo::Direction>();
|
||||||
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
qRegisterMetaType<TransactionHistoryModel::TransactionInfoRole>();
|
||||||
|
|
||||||
|
qmlRegisterType<QrCodeScanner>("moneroComponents.QRCodeScanner", 1, 0, "QRCodeScanner");
|
||||||
|
|
||||||
QQmlApplicationEngine engine;
|
QQmlApplicationEngine engine;
|
||||||
|
|
||||||
OSCursor cursor;
|
OSCursor cursor;
|
||||||
|
@ -167,5 +170,15 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
//WalletManager::instance()->setLogLevel(WalletManager::LogLevel_Max);
|
//WalletManager::instance()->setLogLevel(WalletManager::LogLevel_Max);
|
||||||
|
|
||||||
|
bool builtWithScanner = false;
|
||||||
|
#ifdef WITH_SCANNER
|
||||||
|
builtWithScanner = true;
|
||||||
|
QObject *qmlCamera = rootObject->findChild<QObject*>("qrCameraQML");
|
||||||
|
QCamera *camera_ = qvariant_cast<QCamera*>(qmlCamera->property("mediaObject"));
|
||||||
|
QObject *qmlFinder = rootObject->findChild<QObject*>("QrFinder");
|
||||||
|
qobject_cast<QrCodeScanner*>(qmlFinder)->setSource(camera_);
|
||||||
|
#endif
|
||||||
|
engine.rootContext()->setContextProperty("builtWithScanner", builtWithScanner);
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
7
main.qml
7
main.qml
|
@ -32,6 +32,7 @@ import QtQuick.Controls 1.1
|
||||||
import QtQuick.Controls.Styles 1.1
|
import QtQuick.Controls.Styles 1.1
|
||||||
import QtQuick.Dialogs 1.2
|
import QtQuick.Dialogs 1.2
|
||||||
import Qt.labs.settings 1.0
|
import Qt.labs.settings 1.0
|
||||||
|
import QtMultimedia 5.4
|
||||||
|
|
||||||
import moneroComponents.Wallet 1.0
|
import moneroComponents.Wallet 1.0
|
||||||
import moneroComponents.PendingTransaction 1.0
|
import moneroComponents.PendingTransaction 1.0
|
||||||
|
@ -65,6 +66,7 @@ ApplicationWindow {
|
||||||
property bool viewOnly: false
|
property bool viewOnly: false
|
||||||
property bool foundNewBlock: false
|
property bool foundNewBlock: false
|
||||||
property int timeToUnlock: 0
|
property int timeToUnlock: 0
|
||||||
|
property bool qrScannerEnabled: builtWithScanner && (QtMultimedia.availableCameras.length > 0)
|
||||||
|
|
||||||
// true if wallet ever synchronized
|
// true if wallet ever synchronized
|
||||||
property bool walletInitialized : false
|
property bool walletInitialized : false
|
||||||
|
@ -876,7 +878,10 @@ ApplicationWindow {
|
||||||
messageText: qsTr("Please wait...")
|
messageText: qsTr("Please wait...")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRCodeScanner {
|
||||||
|
id: cameraUi
|
||||||
|
visible : false
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: rootItem
|
id: rootItem
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
|
||||||
QT += qml quick widgets
|
QT += qml quick widgets multimedia
|
||||||
|
|
||||||
WALLET_ROOT=$$PWD/monero
|
WALLET_ROOT=$$PWD/monero
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ QMAKE_DISTCLEAN += -r $$WALLET_ROOT
|
||||||
INCLUDEPATH += $$WALLET_ROOT/include \
|
INCLUDEPATH += $$WALLET_ROOT/include \
|
||||||
$$PWD/src/libwalletqt \
|
$$PWD/src/libwalletqt \
|
||||||
$$PWD/src/QR-Code-generator \
|
$$PWD/src/QR-Code-generator \
|
||||||
|
$$PWD/src/QR-Code-scanner \
|
||||||
$$PWD/src \
|
$$PWD/src \
|
||||||
$$WALLET_ROOT/src
|
$$WALLET_ROOT/src
|
||||||
|
|
||||||
|
@ -37,8 +38,8 @@ HEADERS += \
|
||||||
src/model/AddressBookModel.h \
|
src/model/AddressBookModel.h \
|
||||||
src/libwalletqt/AddressBook.h \
|
src/libwalletqt/AddressBook.h \
|
||||||
src/zxcvbn-c/zxcvbn.h \
|
src/zxcvbn-c/zxcvbn.h \
|
||||||
src/libwalletqt/UnsignedTransaction.h
|
src/libwalletqt/UnsignedTransaction.h \
|
||||||
|
src/QR-Code-scanner/QrCodeScanner.h
|
||||||
|
|
||||||
SOURCES += main.cpp \
|
SOURCES += main.cpp \
|
||||||
filter.cpp \
|
filter.cpp \
|
||||||
|
@ -61,7 +62,8 @@ SOURCES += main.cpp \
|
||||||
src/model/AddressBookModel.cpp \
|
src/model/AddressBookModel.cpp \
|
||||||
src/libwalletqt/AddressBook.cpp \
|
src/libwalletqt/AddressBook.cpp \
|
||||||
src/zxcvbn-c/zxcvbn.c \
|
src/zxcvbn-c/zxcvbn.c \
|
||||||
src/libwalletqt/UnsignedTransaction.cpp
|
src/libwalletqt/UnsignedTransaction.cpp \
|
||||||
|
src/QR-Code-scanner/QrCodeScanner.cpp
|
||||||
|
|
||||||
lupdate_only {
|
lupdate_only {
|
||||||
SOURCES = *.qml \
|
SOURCES = *.qml \
|
||||||
|
@ -76,6 +78,22 @@ LIBS += -L$$WALLET_ROOT/lib \
|
||||||
$$WALLET_ROOT/build/release/contrib/epee/src/libepee.a \
|
$$WALLET_ROOT/build/release/contrib/epee/src/libepee.a \
|
||||||
-lunbound
|
-lunbound
|
||||||
|
|
||||||
|
CONFIG(WITH_SCANNER) {
|
||||||
|
if( greaterThan(QT_MINOR_VERSION, 5) ) {
|
||||||
|
message("using camera scanner")
|
||||||
|
DEFINES += "WITH_SCANNER"
|
||||||
|
HEADERS += src/QR-Code-scanner/QrScanThread.h
|
||||||
|
SOURCES += src/QR-Code-scanner/QrScanThread.cpp
|
||||||
|
android {
|
||||||
|
INCLUDEPATH += $$PWD/../ZBar/include
|
||||||
|
LIBS += -lzbarjni -liconv
|
||||||
|
} else {
|
||||||
|
LIBS += -lzbar
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message("Skipping camera scanner because of Incompatible Qt Version !")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# currently we only support x86 build as qt.io only provides prebuilt qt for x86 mingw
|
# currently we only support x86 build as qt.io only provides prebuilt qt for x86 mingw
|
||||||
|
|
||||||
|
|
|
@ -62,12 +62,31 @@ Rectangle {
|
||||||
tipText: qsTr("<b>Tip tekst test</b>") + translationManager.emptyString
|
tipText: qsTr("<b>Tip tekst test</b>") + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StandardButton {
|
||||||
|
id: qrfinderButton
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 17
|
||||||
|
anchors.topMargin: 5
|
||||||
|
anchors.top: addressLabel.bottom
|
||||||
|
text: qsTr("QRCODE") + translationManager.emptyString
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
visible : appWindow.qrScannerEnabled
|
||||||
|
enabled : visible
|
||||||
|
width: visible ? 60 : 0
|
||||||
|
onClicked: {
|
||||||
|
cameraUi.state = "Capture"
|
||||||
|
cameraUi.qrcode_decoded.connect(updateFromQrCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LineEdit {
|
LineEdit {
|
||||||
id: addressLine
|
id: addressLine
|
||||||
anchors.left: parent.left
|
anchors.left: qrfinderButton.right
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: addressLabel.bottom
|
anchors.top: addressLabel.bottom
|
||||||
anchors.leftMargin: 17
|
|
||||||
anchors.rightMargin: 17
|
anchors.rightMargin: 17
|
||||||
anchors.topMargin: 5
|
anchors.topMargin: 5
|
||||||
error: true;
|
error: true;
|
||||||
|
@ -275,5 +294,13 @@ Rectangle {
|
||||||
root.model = currentWallet.addressBookModel;
|
root.model = currentWallet.addressBookModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
|
||||||
|
console.log("updateFromQrCode")
|
||||||
|
addressLine.text = address
|
||||||
|
paymentIdLine.text = payment_id
|
||||||
|
//amountLine.text = amount
|
||||||
|
descriptionLine.text = recipient_name + " " + tx_description
|
||||||
|
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,15 @@ Rectangle {
|
||||||
privacyLabel.text = qsTr("Privacy level (mixin %1)").arg(mixin) + translationManager.emptyString
|
privacyLabel.text = qsTr("Privacy level (mixin %1)").arg(mixin) + translationManager.emptyString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateFromQrCode(address, payment_id, amount, tx_description, recipient_name) {
|
||||||
|
console.log("updateFromQrCode")
|
||||||
|
addressLine.text = address
|
||||||
|
paymentIdLine.text = payment_id
|
||||||
|
amountLine.text = amount
|
||||||
|
descriptionLine.text = recipient_name + " " + tx_description
|
||||||
|
cameraUi.qrcode_decoded.disconnect(updateFromQrCode)
|
||||||
|
}
|
||||||
|
|
||||||
// Information dialog
|
// Information dialog
|
||||||
StandardDialog {
|
StandardDialog {
|
||||||
// dynamically change onclose handler
|
// dynamically change onclose handler
|
||||||
|
@ -249,11 +258,29 @@ Rectangle {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: addressLabel.bottom
|
anchors.top: addressLabel.bottom
|
||||||
|
|
||||||
|
StandardButton {
|
||||||
|
id: qrfinderButton
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: 17
|
||||||
|
anchors.topMargin: 5
|
||||||
|
text: qsTr("QRCODE") + translationManager.emptyString
|
||||||
|
shadowReleasedColor: "#FF4304"
|
||||||
|
shadowPressedColor: "#B32D00"
|
||||||
|
releasedColor: "#FF6C3C"
|
||||||
|
pressedColor: "#FF4304"
|
||||||
|
visible : appWindow.qrScannerEnabled
|
||||||
|
enabled : visible
|
||||||
|
width: visible ? 60 : 0
|
||||||
|
onClicked: {
|
||||||
|
cameraUi.state = "Capture"
|
||||||
|
cameraUi.qrcode_decoded.connect(updateFromQrCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
LineEdit {
|
LineEdit {
|
||||||
id: addressLine
|
id: addressLine
|
||||||
anchors.left: parent.left
|
anchors.left: qrfinderButton.right
|
||||||
anchors.right: resolveButton.left
|
anchors.right: resolveButton.left
|
||||||
anchors.leftMargin: 17
|
//anchors.leftMargin: 17
|
||||||
anchors.topMargin: 5
|
anchors.topMargin: 5
|
||||||
placeholderText: "4..."
|
placeholderText: "4..."
|
||||||
// validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }
|
// validator: RegExpValidator { regExp: /[0-9A-Fa-f]{95}/g }
|
||||||
|
|
1
qml.qrc
1
qml.qrc
|
@ -125,5 +125,6 @@
|
||||||
<file>wizard/WizardPasswordUI.qml</file>
|
<file>wizard/WizardPasswordUI.qml</file>
|
||||||
<file>wizard/WizardCreateViewOnlyWallet.qml</file>
|
<file>wizard/WizardCreateViewOnlyWallet.qml</file>
|
||||||
<file>components/DaemonConsole.qml</file>
|
<file>components/DaemonConsole.qml</file>
|
||||||
|
<file>components/QRCodeScanner.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
108
src/QR-Code-scanner/QrCodeScanner.cpp
Normal file
108
src/QR-Code-scanner/QrCodeScanner.cpp
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
// Copyright (c) 2014-2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
#ifdef WITH_SCANNER
|
||||||
|
m_probe = new QVideoProbe(this);
|
||||||
|
m_thread = new QrScanThread(this);
|
||||||
|
m_thread->start();
|
||||||
|
QObject::connect(m_thread, SIGNAL(decoded(int,QString)), this, SLOT(processCode(int,QString)));
|
||||||
|
QObject::connect(m_thread, SIGNAL(notifyError(const QString &, bool)), this, SIGNAL(notifyError(const QString &, bool)));
|
||||||
|
connect(m_probe, SIGNAL(videoFrameProbed(QVideoFrame)), this, SLOT(processFrame(QVideoFrame)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void QrCodeScanner::setSource(QCamera *camera)
|
||||||
|
{
|
||||||
|
m_probe->setSource(camera);
|
||||||
|
}
|
||||||
|
void QrCodeScanner::processCode(int type, const QString &data)
|
||||||
|
{
|
||||||
|
if (! m_enabled) return;
|
||||||
|
qDebug() << "decoded - type: " << type << " data: " << data;
|
||||||
|
QString address, payment_id, tx_description, recipient_name, error;
|
||||||
|
QVector<QString> unknown_parameters;
|
||||||
|
uint64_t amount(0);
|
||||||
|
if( ! WalletManager::instance()->parse_uri(data, address, payment_id, amount, tx_description, recipient_name, unknown_parameters, error) )
|
||||||
|
{
|
||||||
|
qDebug() << "Failed to parse_uri : " << error;
|
||||||
|
emit notifyError(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(unknown_parameters.size() > 0)
|
||||||
|
{
|
||||||
|
qDebug() << "unknown parameters " << unknown_parameters;
|
||||||
|
emit notifyError(error, true);
|
||||||
|
}
|
||||||
|
qDebug() << "Parsed URI : " << address << " " << payment_id << " " << amount << " " << tx_description << " " << recipient_name << " " << error;
|
||||||
|
QString s_amount = WalletManager::instance()->displayAmount(amount);
|
||||||
|
qDebug() << "Amount passed " << s_amount ;
|
||||||
|
emit decoded(address, payment_id, s_amount, tx_description, recipient_name);
|
||||||
|
}
|
||||||
|
void QrCodeScanner::processFrame(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();
|
||||||
|
}
|
||||||
|
#ifdef WITH_SCANNER
|
||||||
|
void QrCodeScanner::timerEvent(QTimerEvent *event)
|
||||||
|
{
|
||||||
|
if( (event->timerId() == m_processTimerId) ){
|
||||||
|
m_thread->addFrame(m_curFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
79
src/QR-Code-scanner/QrCodeScanner.h
Normal file
79
src/QR-Code-scanner/QrCodeScanner.h
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// Copyright (c) 2014-2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#ifndef QRCODESCANNER_H_
|
||||||
|
#define QRCODESCANNER_H_
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
#include <QVideoFrame>
|
||||||
|
#ifdef WITH_SCANNER
|
||||||
|
#include "QrScanThread.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void setSource(QCamera*);
|
||||||
|
|
||||||
|
bool enabled() const;
|
||||||
|
void setEnabled(bool enabled);
|
||||||
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void processCode(int type, const QString &data);
|
||||||
|
void processFrame(QVideoFrame);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void enabledChanged();
|
||||||
|
|
||||||
|
void decoded(const QString &address, const QString &payment_id, const QString &amount, const QString &tx_description, const QString &recipient_name);
|
||||||
|
void decode(int type, const QString &data);
|
||||||
|
void notifyError(const QString &error, bool warning = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
#ifdef WITH_SCANNER
|
||||||
|
void timerEvent(QTimerEvent *);
|
||||||
|
QrScanThread *m_thread;
|
||||||
|
#endif
|
||||||
|
int m_processTimerId;
|
||||||
|
int m_processInterval;
|
||||||
|
int m_enabled;
|
||||||
|
QVideoFrame m_curFrame;
|
||||||
|
QVideoProbe *m_probe;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
132
src/QR-Code-scanner/QrScanThread.cpp
Normal file
132
src/QR-Code-scanner/QrScanThread.cpp
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
// Copyright (c) 2014-2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#include "QrScanThread.h"
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
|
||||||
|
extern QImage qt_imageFromVideoFrame(const QVideoFrame &f);
|
||||||
|
#else
|
||||||
|
QImage qt_imageFromVideoFrame(const QVideoFrame &f){
|
||||||
|
Q_ASSERT_X(0 != 0, "qt_imageFromVideoFrame", "Should have been managed in .pro");
|
||||||
|
return QImage();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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.byteCount();
|
||||||
|
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( qt_imageFromVideoFrame(frame) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QrScanThread::stop()
|
||||||
|
{
|
||||||
|
m_running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_waitCondition.wait(&m_mutex);
|
||||||
|
processVideoFrame(m_queue.takeFirst());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
69
src/QR-Code-scanner/QrScanThread.h
Normal file
69
src/QR-Code-scanner/QrScanThread.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// Copyright (c) 2014-2017, The Monero Project
|
||||||
|
//
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other
|
||||||
|
// materials provided with the distribution.
|
||||||
|
//
|
||||||
|
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||||
|
// used to endorse or promote products derived from this software without specific
|
||||||
|
// prior written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||||
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||||
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void decoded(int type, const QString &data);
|
||||||
|
void notifyError(const QString &error, bool warning = false);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void run();
|
||||||
|
virtual void stop();
|
||||||
|
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
|
Loading…
Reference in a new issue