Implement Qr-code generation and scanning
This commit is contained in:
parent
8d1f0173ed
commit
06e76bc287
13 changed files with 400 additions and 63 deletions
|
@ -98,6 +98,12 @@ ios {
|
|||
xcode_product_bundle_identifier_setting.value = "de.itsblue.bluerock"
|
||||
}
|
||||
|
||||
CONFIG += enable_decoder_qr_code \
|
||||
enable_encoder_qr_code \
|
||||
qzxing_multimedia \
|
||||
qzxing_qml
|
||||
include(qzxing/src/QZXing-components.pri)
|
||||
|
||||
# this has to be the last line!
|
||||
ANDROID_ABIS = armeabi-v7a arm64-v8a
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <QTextCursor>
|
||||
#include <QPageSize>
|
||||
#include <QPdfWriter>
|
||||
#include "QZXing.h"
|
||||
|
||||
#include "shareUtils/shareutils.h"
|
||||
|
||||
|
@ -43,9 +44,10 @@ public:
|
|||
explicit BlueRockBackend(QObject *parent = nullptr);
|
||||
|
||||
private:
|
||||
QVariantMap senddata(QUrl serviceUrl, QUrlQuery pdata = QUrlQuery());
|
||||
QVariantMap _senddata(QUrl serviceUrl, QUrlQuery pdata = QUrlQuery());
|
||||
|
||||
ShareUtils* _shareUtils;
|
||||
const QStringList _validBaseDomains = {"digitalrock.de", "bluerock.dev"};
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -53,8 +55,8 @@ public slots:
|
|||
|
||||
QVariant getWidgetData(QVariantMap params);
|
||||
QVariantMap getParamsFromUrl(QString url);
|
||||
void shareResultsAsUrl(QString url);
|
||||
void shareResultsAsPoster(QString url);
|
||||
void shareResultsAsUrl(QString url, QString compName);
|
||||
void shareResultsAsPoster(QString url, QString compName);
|
||||
|
||||
};
|
||||
|
||||
|
|
203
resources/qml/Components/QrCodeScanPopup.qml
Normal file
203
resources/qml/Components/QrCodeScanPopup.qml
Normal file
|
@ -0,0 +1,203 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QZXing 3.1
|
||||
import QtMultimedia 5.12
|
||||
import QtQuick.Shapes 1.12
|
||||
import QtQuick.Controls.Material 2.12
|
||||
|
||||
|
||||
Dialog {
|
||||
id: control
|
||||
|
||||
property string _statusText: ""
|
||||
property string _statusColor: Material.primaryTextColor
|
||||
property bool _freezeScanning: false
|
||||
|
||||
parent: Overlay.overlay
|
||||
|
||||
x: (parent.width - width) * 0.5
|
||||
y: (parent.height - height) * 0.5
|
||||
|
||||
height: app.height * 0.8
|
||||
width: app.width * 0.8
|
||||
|
||||
modal: true
|
||||
title: "Scan QR-Code"
|
||||
|
||||
standardButtons: Dialog.Cancel
|
||||
|
||||
onOpened: {
|
||||
setDefaultStatusText()
|
||||
control._freezeScanning = false
|
||||
cameraLoader.sourceComponent = cameraComponent
|
||||
}
|
||||
|
||||
onClosed: cameraLoader.sourceComponent = null
|
||||
|
||||
function setDefaultStatusText() {
|
||||
_statusText = "Place the Code in the center"
|
||||
_statusColor = Material.primaryTextColor
|
||||
}
|
||||
|
||||
contentItem: Loader {
|
||||
id: cameraLoader
|
||||
|
||||
asynchronous: true
|
||||
sourceComponent: null
|
||||
}
|
||||
|
||||
Component {
|
||||
id: cameraComponent
|
||||
Item {
|
||||
anchors.fill: parent
|
||||
|
||||
Camera {
|
||||
id: camera
|
||||
captureMode: Camera.CaptureStillImage
|
||||
imageProcessing.whiteBalanceMode: CameraImageProcessing.WhiteBalanceAuto
|
||||
|
||||
focus {
|
||||
focusMode: Camera.FocusContinuous
|
||||
focusPointMode: Camera.FocusPointCenter
|
||||
}
|
||||
}
|
||||
|
||||
VideoOutput {
|
||||
id: videoOutput
|
||||
x: 0
|
||||
y: 0
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
fillMode: VideoOutput.PreserveAspectCrop
|
||||
|
||||
source: camera
|
||||
filters: [ zxingFilter ]
|
||||
focus : visible // to receive focus and capture key events when visible
|
||||
|
||||
autoOrientation: true
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
if (camera.lockStatus !== Camera.Unlocked)
|
||||
camera.unlock();
|
||||
|
||||
camera.searchAndLock();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: app.landscape() ? focusIndicatorRect.left : parent.right
|
||||
bottom: app.landscape() ? parent.bottom : focusIndicatorRect.top
|
||||
}
|
||||
|
||||
opacity: focusIndicatorRect.opacity
|
||||
color: focusIndicatorRect.border.color
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: focusIndicatorRect
|
||||
anchors.centerIn: parent
|
||||
|
||||
width: Math.min(parent.height, parent.width)
|
||||
height: width
|
||||
|
||||
border.width: width * 0.1
|
||||
border.color: "#000000"
|
||||
|
||||
opacity: 0.3
|
||||
color: "transparent"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
bottom: focusIndicatorRect.bottom
|
||||
bottomMargin: height * 0.5
|
||||
horizontalCenter: focusIndicatorRect.horizontalCenter
|
||||
}
|
||||
|
||||
width: (focusIndicatorRect.width - focusIndicatorRect.border.width * 2) * 0.8
|
||||
height: focusIndicatorRect.border.width
|
||||
|
||||
radius: height * 0.3
|
||||
|
||||
color: Material.backgroundColor
|
||||
|
||||
Material.elevation: 10
|
||||
|
||||
|
||||
Label {
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: height * 0.1
|
||||
}
|
||||
|
||||
color: control._statusColor
|
||||
|
||||
font.pixelSize: height * 0.5
|
||||
fontSizeMode: Text.Fit
|
||||
minimumPixelSize: height * 0.2
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: control._statusText
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
top: app.landscape() ? parent.top : focusIndicatorRect.bottom
|
||||
left: app.landscape() ? focusIndicatorRect.right : parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
opacity: focusIndicatorRect.opacity
|
||||
color: focusIndicatorRect.border.color
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QZXingFilter {
|
||||
id: zxingFilter
|
||||
|
||||
decoder {
|
||||
onTagFound: {
|
||||
if(control._freezeScanning)
|
||||
return
|
||||
|
||||
control._freezeScanning = true
|
||||
|
||||
control._statusText = "Plase wait..."
|
||||
|
||||
if(app.openWidgetFromUrl(tag))
|
||||
control.close()
|
||||
else {
|
||||
control._statusText = "Invalid QR-Code"
|
||||
control._statusColor = Material.color(Material.Red)
|
||||
statusTextResetTimer.start()
|
||||
control._freezeScanning = false
|
||||
}
|
||||
}
|
||||
|
||||
enabledDecoders: QZXing.DecoderFormat_QR_CODE
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: statusTextResetTimer
|
||||
running: false
|
||||
repeat: false
|
||||
interval: 3000
|
||||
onTriggered: setDefaultStatusText()
|
||||
}
|
||||
}
|
|
@ -226,7 +226,7 @@ ColoredItemDelegate {
|
|||
|
||||
// outline
|
||||
context.lineWidth = 1;
|
||||
context.strokeStyle = '#424242';
|
||||
context.strokeStyle = Material.primaryTextColor;
|
||||
context.stroke();
|
||||
|
||||
if(resultData[1] > 0){
|
||||
|
@ -254,7 +254,7 @@ ColoredItemDelegate {
|
|||
|
||||
// outline
|
||||
context.lineWidth = 1;
|
||||
context.strokeStyle = '#424242';
|
||||
context.strokeStyle = Material.primaryTextColor;
|
||||
context.stroke();
|
||||
|
||||
|
||||
|
@ -279,7 +279,7 @@ ColoredItemDelegate {
|
|||
|
||||
// outline
|
||||
context.lineWidth = 1;
|
||||
context.strokeStyle = '#424242';
|
||||
context.strokeStyle = Material.primaryTextColor;
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import QtQuick 2.0
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QZXing 3.1
|
||||
|
||||
Dialog {
|
||||
id: control
|
||||
|
||||
property string _shareUrl
|
||||
property string _compName
|
||||
|
||||
parent: Overlay.overlay
|
||||
|
||||
|
@ -13,15 +15,35 @@ Dialog {
|
|||
y: (parent.height - height) * 0.5
|
||||
|
||||
modal: true
|
||||
|
||||
title: "Share these results"
|
||||
|
||||
contentItem: RowLayout {
|
||||
onClosed: {
|
||||
shareComponentLoader.sourceComponent = null
|
||||
}
|
||||
|
||||
contentItem: Loader {
|
||||
id: shareComponentLoader
|
||||
|
||||
asynchronous: false
|
||||
sourceComponent: null
|
||||
}
|
||||
|
||||
Component {
|
||||
id: shareComponent
|
||||
StackLayout {
|
||||
id: stackLayout
|
||||
currentIndex: 0
|
||||
|
||||
RowLayout {
|
||||
id: menuRow
|
||||
Repeater {
|
||||
id: buttonRepeater
|
||||
property var buttons: [
|
||||
["\uf0c1", "Link", serverConn.shareResultsAsUrl],
|
||||
["\uf029", "QR-code", null],
|
||||
["\uf029", "QR-code", function() {
|
||||
stackLayout.currentIndex = 1
|
||||
}
|
||||
],
|
||||
["\uf1c1", "Poster", serverConn.shareResultsAsPoster],
|
||||
]
|
||||
|
||||
|
@ -31,13 +53,40 @@ Dialog {
|
|||
flat: true
|
||||
font.family: fa5solid.name
|
||||
text: "<font size=\"+4\">" + modelData[0] + "</font><br><br> " + modelData[1] + " "
|
||||
onClicked: buttonRepeater.buttons[index][2](_shareUrl)
|
||||
onClicked: buttonRepeater.buttons[index][2](_shareUrl, _compName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function appear(shareUrl) {
|
||||
|
||||
Image {
|
||||
id: qrCodeImage
|
||||
|
||||
property int size: stackLayout.currentIndex === 1 ? (app.landscape() ? app.height * 0.8 : app.width * 0.8):menuRow.height
|
||||
|
||||
Layout.preferredHeight: size
|
||||
Layout.preferredWidth: size
|
||||
|
||||
sourceSize.width: size
|
||||
sourceSize.height: size
|
||||
|
||||
fillMode: Image.PreserveAspectFit
|
||||
|
||||
source: "image://QZXing/encode/" + _shareUrl + "?border=true&correctionLevel=H"
|
||||
|
||||
Behavior on size {
|
||||
NumberAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function appear(shareUrl, compName) {
|
||||
_shareUrl = shareUrl
|
||||
_compName = compName
|
||||
shareComponentLoader.sourceComponent = shareComponent
|
||||
control.open()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ Page {
|
|||
topMargin: root.height * 0.03
|
||||
}
|
||||
|
||||
height: menuGr.buttonSize * 0.3
|
||||
height: app.landscape() ? menuGr.buttonSize * 0.2:menuGr.buttonSize * 0.3
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
|
@ -84,7 +84,7 @@ Page {
|
|||
}
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
Grid {
|
||||
id: footerMenu
|
||||
|
||||
anchors {
|
||||
|
@ -93,6 +93,11 @@ Page {
|
|||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
width: app.landscape() ? childrenRect.width : parent.width * 0.8
|
||||
height: app.landscape() ? headerBadge.height : headerBadge.height * 2
|
||||
|
||||
columnSpacing: height * 0.1
|
||||
|
||||
columns: app.landscape() ? 4:2
|
||||
rows: app.landscape() ? 1:2
|
||||
|
||||
|
@ -102,18 +107,19 @@ Page {
|
|||
["\uf059", "IFSC results", ifscDisclaimerDialog.open],
|
||||
["\uf042", Material.theme === Material.Light ? "Dark mode":"Light mode", app.toggleDarkMode],
|
||||
["\uf05a", "About blueROCK", aboutBluerockDisclaimerDialog.open],
|
||||
["\uf029", "Scan QR code", null],
|
||||
["\uf029", "Scan QR code", qrCodeScanPopup.open],
|
||||
]
|
||||
|
||||
model: buttons
|
||||
|
||||
delegate: Item {
|
||||
|
||||
Layout.preferredWidth: app.landscape() ? footerMenuButton.implicitWidth : root.width * 0.5 - (footerMenu.columnSpacing / 2)
|
||||
Layout.preferredHeight: footerMenuButton.implicitHeight
|
||||
width: app.landscape() ? footerMenuButton.implicitWidth : footerMenu.width * 0.5 - (footerMenu.columnSpacing / 2)
|
||||
height: app.landscape() ? footerMenu.height : footerMenu.height * 0.5 - (footerMenu.rowSpacing / 2)
|
||||
|
||||
Button {
|
||||
id: footerMenuButton
|
||||
|
||||
property bool isLeft: index % 2 === 0
|
||||
|
||||
anchors {
|
||||
|
@ -122,6 +128,8 @@ Page {
|
|||
centerIn: app.landscape() ? parent : undefined
|
||||
}
|
||||
|
||||
height: parent.height
|
||||
|
||||
flat: true
|
||||
|
||||
font.family: fa5solid.name
|
||||
|
@ -157,7 +165,11 @@ Page {
|
|||
"This app is open source and licensed under the <a href='https://www.gnu.org/licenses/agpl-3.0.en.html'>GNU agplV3 license</a>," +
|
||||
"the source code can be found <a href='https://itsblue.dev/dorian/blueROCK/'>here</a>.<br><br>" +
|
||||
"Resultservice and rankings provided by <a href='http://www.digitalROCK.de'>digital ROCK</a>."
|
||||
}
|
||||
|
||||
QrCodeScanPopup {
|
||||
id: qrCodeScanPopup
|
||||
Material.theme: root.Material.theme
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,7 +38,9 @@ Page {
|
|||
Result,
|
||||
|
||||
Ranking,
|
||||
Aggregated // not yet implemented
|
||||
Aggregated, // not yet implemented
|
||||
|
||||
Invalid
|
||||
}
|
||||
|
||||
title: widgetLd.item !== null && widgetLd.item.hasOwnProperty('title') ? widgetLd.item['title']:""
|
||||
|
@ -72,7 +74,6 @@ Page {
|
|||
// route: (int) round
|
||||
// type: ('','starters', 'nat_team_ranking', 'sektionenwertung', 'regionalzentren'),
|
||||
//}
|
||||
|
||||
var ret = serverConn.getWidgetData(params)
|
||||
|
||||
root.status = ret["status"]
|
||||
|
@ -80,7 +81,11 @@ Page {
|
|||
if(ret["status"] === 200){
|
||||
root.widgetData = ret["data"]
|
||||
root.widgetType = checkWidgetType(params, root.widgetData)
|
||||
if(widgetLd.load()){
|
||||
if(widgetType === WidgetPage.WidgetType.Invalid) {
|
||||
root.ready = false
|
||||
root.status = 906
|
||||
}
|
||||
else if(widgetLd.load()){
|
||||
root.ready = true
|
||||
}
|
||||
else {
|
||||
|
@ -124,6 +129,10 @@ Page {
|
|||
|
||||
}
|
||||
|
||||
function areParamsValid() {
|
||||
|
||||
}
|
||||
|
||||
function checkWidgetType(params, widgetData){
|
||||
var widgetType
|
||||
|
||||
|
@ -170,6 +179,9 @@ Page {
|
|||
// aggregated
|
||||
widgetType = WidgetPage.WidgetType.Aggregated
|
||||
}
|
||||
else {
|
||||
widgetType = WidgetPage.WidgetType.Invalid
|
||||
}
|
||||
|
||||
return widgetType
|
||||
}
|
||||
|
@ -181,10 +193,9 @@ Page {
|
|||
return ret.join('&');
|
||||
}
|
||||
|
||||
function shareWidget() {
|
||||
function shareWidget(compName) {
|
||||
var url = "https://l.bluerock.dev/?" + encodeQueryData(params)
|
||||
sharePu.appear(url)
|
||||
console.log("Url will be:", url)
|
||||
sharePu.appear(url, compName)
|
||||
}
|
||||
|
||||
Loader {
|
||||
|
|
|
@ -69,7 +69,7 @@ DataListView {
|
|||
ToolButton {
|
||||
id: shareToolBt
|
||||
|
||||
onClicked: shareWidget()
|
||||
onClicked: shareWidget(control.title)
|
||||
|
||||
text: "\uf1e0"
|
||||
font.family: fa5solid.name
|
||||
|
|
|
@ -28,6 +28,8 @@ import de.itsblue.blueROCK 1.0
|
|||
import "./Pages"
|
||||
import "./Components"
|
||||
|
||||
import "./Widgets"
|
||||
|
||||
Window {
|
||||
visible: true
|
||||
width: 540
|
||||
|
@ -115,7 +117,7 @@ Window {
|
|||
'sui_ice' : {
|
||||
'label' : 'Iceclimbing',
|
||||
'nation' : 'SUI',
|
||||
'wettk_reg' : '^[0-9]{2,2}_RC_.*',
|
||||
'wparams["valid"]ettk_reg' : '^[0-9]{2,2}_RC_.*',
|
||||
'rang_title': '',
|
||||
'bgcolor' : app.federalColor, //'#F0F0F0',
|
||||
'sort_rank': 4,
|
||||
|
@ -134,6 +136,7 @@ Window {
|
|||
//mainStack.push("Pages/AthleteSearchPage.qml")
|
||||
openWidget({comp: 11651, cat: 26})
|
||||
//openWidget({person: 6623})
|
||||
//console.log(JSON.stringify(serverConn.getParamsFromUrl("")))
|
||||
}
|
||||
|
||||
FontLoader {
|
||||
|
@ -154,11 +157,6 @@ Window {
|
|||
|
||||
BlueRockBackend {
|
||||
id: serverConn
|
||||
|
||||
Component.onCompleted: {
|
||||
//var params = serverConn.getParamsFromUrl("https://www.digitalrock.de/egroupware/ranking/sitemgr/digitalrock/eliste.html#!comp=11471&cat=GER_F_A")
|
||||
//app.openWidget(params)
|
||||
}
|
||||
}
|
||||
|
||||
AppSettings {
|
||||
|
@ -539,17 +537,36 @@ Window {
|
|||
function openWidget(params) {
|
||||
loadingDl.open()
|
||||
|
||||
console.log("Opening widget: ", JSON.stringify(params))
|
||||
|
||||
var result = false
|
||||
|
||||
if(Object.keys(params).length) {
|
||||
var calComp = Qt.createComponent("qrc:/Pages/WidgetPage.qml").createObject(null, {"params": params})
|
||||
app.errorCode = calComp.status
|
||||
|
||||
if(calComp.ready) {
|
||||
mainStack.push(calComp)
|
||||
result = true
|
||||
}
|
||||
else {
|
||||
delete(calComp)
|
||||
}
|
||||
}
|
||||
|
||||
loadingDl.close()
|
||||
return result
|
||||
}
|
||||
|
||||
function openWidgetFromUrl(url) {
|
||||
var result = serverConn.getParamsFromUrl(url)
|
||||
|
||||
if(result["valid"]) {
|
||||
openWidget(result["params"])
|
||||
return app.errorCode !== 906
|
||||
}
|
||||
|
||||
return result["valid"]
|
||||
}
|
||||
|
||||
function defaultString(string, defaultString) {
|
||||
|
@ -592,6 +609,11 @@ Window {
|
|||
errorString = "Authentication required"
|
||||
errorDescription = "The server asked for user credentinals, please chack them and try again"
|
||||
break
|
||||
case 404:
|
||||
infoLevel = 2
|
||||
errorString = "Not found"
|
||||
errorDescription = "The requested item was not found"
|
||||
break
|
||||
case 500:
|
||||
infoLevel = 2
|
||||
errorString = "Internal server error"
|
||||
|
@ -627,6 +649,11 @@ Window {
|
|||
errorString = "Loading..."
|
||||
errorDescription = "Please wait while we're loading some data"
|
||||
break
|
||||
case 906:
|
||||
infoLevel = 2
|
||||
errorString = "Invalid Request"
|
||||
errorDescription = "Invalid Request"
|
||||
break
|
||||
default:
|
||||
infoLevel = 2
|
||||
errorString = "Unexpected error ("+errorCode+")"
|
||||
|
|
|
@ -29,5 +29,6 @@
|
|||
<file>Components/ColoredItemDelegate.qml</file>
|
||||
<file>Components/AlignedButton.qml</file>
|
||||
<file>Components/SharePopup.qml</file>
|
||||
<file>Components/QrCodeScanPopup.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
Binary file not shown.
|
@ -21,7 +21,6 @@
|
|||
BlueRockBackend::BlueRockBackend(QObject *parent) : QObject(parent)
|
||||
{
|
||||
this->_shareUtils = new ShareUtils(this);
|
||||
this->shareResultsAsPoster("test");
|
||||
}
|
||||
|
||||
QVariant BlueRockBackend::getWidgetData(QVariantMap params) {
|
||||
|
@ -49,7 +48,7 @@ QVariant BlueRockBackend::getWidgetData(QVariantMap params) {
|
|||
|
||||
qDebug() << requestUrl;
|
||||
|
||||
QVariantMap ret = this->senddata(QUrl(requestUrl));
|
||||
QVariantMap ret = this->_senddata(QUrl(requestUrl));
|
||||
|
||||
if(ret["status"] != 200) {
|
||||
// request was a failure
|
||||
|
@ -67,6 +66,18 @@ QVariant BlueRockBackend::getWidgetData(QVariantMap params) {
|
|||
QVariantMap BlueRockBackend::getParamsFromUrl(QString stringUrl) {
|
||||
stringUrl = stringUrl.replace("#!", "?");
|
||||
QUrl url(stringUrl);
|
||||
|
||||
if(!url.isValid() || url.isEmpty() || url.host().isEmpty())
|
||||
return {{"valid", false},{"params", QVariantMap()}} ;
|
||||
|
||||
QStringList domainFragments = url.host().split(".");
|
||||
QString tld = domainFragments.takeLast();
|
||||
QString domainName = domainFragments.takeLast();
|
||||
QString baseDomain = domainName + "." + tld;
|
||||
|
||||
if(!this->_validBaseDomains.contains(baseDomain))
|
||||
return {{"valid", false},{"params", QVariantMap()}};
|
||||
|
||||
QUrlQuery query(url.query());
|
||||
|
||||
QVariantMap params;
|
||||
|
@ -78,31 +89,42 @@ QVariantMap BlueRockBackend::getParamsFromUrl(QString stringUrl) {
|
|||
params.insert(pair.first, pair.second);
|
||||
}
|
||||
|
||||
return params;
|
||||
return {{"valid", true},{"params",params}};
|
||||
}
|
||||
|
||||
void BlueRockBackend::shareResultsAsUrl(QString url) {
|
||||
this->_shareUtils->shareText(url);
|
||||
void BlueRockBackend::shareResultsAsUrl(QString url, QString compName) {
|
||||
this->_shareUtils->shareText("Check out the results of " + compName + " over here:\n" + url);
|
||||
}
|
||||
|
||||
void BlueRockBackend::shareResultsAsPoster(QString url) {
|
||||
QPdfWriter writer("/tmp/test.pdf");
|
||||
void BlueRockBackend::shareResultsAsPoster(QString url, QString compName) {
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
|
||||
path += "/" + compName + ".pdf";
|
||||
QPdfWriter writer(path);
|
||||
writer.setPageSize(QPageSize(QPageSize::A4));
|
||||
writer.setPageMargins(QMargins(0, 0, 0, 0));
|
||||
writer.setResolution(600);
|
||||
|
||||
QPainter painter(&writer);
|
||||
painter.drawText(QRect(0, 0, 1980, 100),Qt::AlignHCenter|Qt::AlignBottom,
|
||||
"Children's Health Checkup Form");
|
||||
QPixmap image(":/PosterTemplate.png");
|
||||
painter.drawPixmap(0,0, writer.width(), writer.height(), image);
|
||||
QPixmap background(":/PosterTemplate.png");
|
||||
painter.drawPixmap(0,0, writer.width(), writer.height(), background);
|
||||
|
||||
QPixmap barcode;
|
||||
int size = writer.width() * 0.5;
|
||||
QZXingEncoderConfig encoderConfig(QZXing::EncoderFormat_QR_CODE, QSize(size, size), QZXing::EncodeErrorCorrectionLevel_M, false, false);
|
||||
barcode.convertFromImage(QZXing::encodeData(url, encoderConfig));
|
||||
painter.drawPixmap((writer.width() - size) / 2, size * 0.5, size, size, barcode);
|
||||
|
||||
painter.end();
|
||||
|
||||
int requestId;
|
||||
this->_shareUtils->sendFile(path, compName, "application/pdf", requestId);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// --- Helper functions ---
|
||||
// ------------------------
|
||||
|
||||
QVariantMap BlueRockBackend::senddata(QUrl serviceUrl, QUrlQuery pdata)
|
||||
QVariantMap BlueRockBackend::_senddata(QUrl serviceUrl, QUrlQuery pdata)
|
||||
{
|
||||
// create network manager
|
||||
QNetworkAccessManager * networkManager = new QNetworkAccessManager();
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <QQmlApplicationEngine>
|
||||
#include <QStyleFactory>
|
||||
#include <QUrl>
|
||||
#include "QZXing.h"
|
||||
|
||||
#include "headers/bluerockbackend.h"
|
||||
#include "headers/appsettings.h"
|
||||
|
@ -46,6 +47,9 @@ int main(int argc, char *argv[])
|
|||
engine.rootContext()->setContextProperty("QT_DEBUG", false);
|
||||
#endif
|
||||
|
||||
QZXing::registerQMLTypes();
|
||||
QZXing::registerQMLImageProvider(engine);
|
||||
|
||||
engine.rootContext()->setContextProperty("APP_VERSION", APP_VERSION);
|
||||
|
||||
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
|
||||
|
|
Loading…
Reference in a new issue