app/resources/qml/Pages/QrCodeScanPage.qml

299 lines
8.1 KiB
QML
Raw Permalink Normal View History

import QtQuick 2.0
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
2023-07-05 16:27:15 +02:00
import QZXing 3.3
import QtMultimedia 5.12
import QtQuick.Shapes 1.12
import QtQuick.Controls.Material 2.12
2021-06-25 09:41:07 +02:00
import "../Components"
2021-06-25 09:41:07 +02:00
Page {
id: control
property string _statusText: ""
property string _statusColor: Material.primaryTextColor
property bool _freezeScanning: false
2021-06-25 09:41:07 +02:00
signal headerComponentChanged()
2021-06-20 20:11:19 +02:00
//% "Scan QR-Code"
2021-06-20 21:08:59 +02:00
title: qsTrId("#scanQrCode")
2021-06-25 09:41:07 +02:00
onFocusChanged: focus ? open() : close()
2021-06-25 09:41:07 +02:00
function open() {
_setDefaultStatusText()
control._freezeScanning = false
if(serverConn.isCameraPermissionGranted())
cameraLoader.sourceComponent = cameraComponent
else
cameraLoader.sourceComponent = noPermissionComponent
}
2021-06-25 09:41:07 +02:00
function close() {
cameraLoader.sourceComponent = null
}
2021-06-25 09:41:07 +02:00
function _setDefaultStatusText() {
2021-06-20 20:11:19 +02:00
//% "Place the Code in the center"
2021-06-20 21:08:59 +02:00
_statusText = qsTrId("#placeQrCodeInCenter")
_statusColor = Material.primaryTextColor
}
2021-06-25 09:41:07 +02:00
function _handleTag(tag) {
if(control._freezeScanning)
return
control._freezeScanning = true
//% "Plase wait"
control._statusText = qsTrId("#pleaseWait") + "..."
if(app.openWidgetFromUrl(tag))
control.close()
else {
//% "Invalid QR-Code"
control._statusText = qsTrId("#invalidQrCode")
control._statusColor = Material.color(Material.Red)
statusTextResetTimer.start()
control._freezeScanning = false
}
}
function _requestCameraPermission() {
var permissionGranted = serverConn.requestCameraPermission()
if(permissionGranted)
cameraLoader.sourceComponent = cameraComponent
}
contentItem: Loader {
id: cameraLoader
2021-06-25 09:41:07 +02:00
anchors.fill: parent
//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
}
}
2021-06-25 09:41:07 +02:00
FancyBusyIndicator {
anchors.centerIn: parent
}
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"
2021-06-25 09:41:07 +02:00
opacity: 0.5
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
}
}
}
}
Component {
id: noPermissionComponent
2021-06-25 09:41:07 +02:00
ColumnLayout {
//anchors.fill: parent
//anchors.margins: app.landscape() ? app.height * 0.1 : app.width * 0.1
property int columnWidth: control.width * 0.9
spacing: height * 0.02
Item {
Layout.fillHeight: true
}
Label {
id: noPermissionIcon
2021-06-25 09:41:07 +02:00
Layout.preferredWidth: parent.columnWidth
Layout.alignment: Layout.Center
font.pixelSize: app.landscape() ? parent.height * 0.25:parent.height * 0.15
font.family: fa5solid.name
2021-06-25 09:41:07 +02:00
horizontalAlignment: Text.AlignHCenter
text: "\uf3ed"
}
Label {
id: noPermissionText
2021-06-25 09:41:07 +02:00
Layout.preferredWidth: parent.columnWidth
Layout.alignment: Layout.Center
font.bold: true
2021-06-25 09:41:07 +02:00
font.pixelSize: noPermissionIcon.height * 0.2
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
2021-06-25 09:41:07 +02:00
//% "Camera access required"
text: qsTrId("#cameraPermissionDenied")
}
Label {
id: noPermissionDetailText
2021-06-25 09:41:07 +02:00
Layout.preferredWidth: parent.columnWidth
Layout.alignment: Layout.Center
font.pixelSize: noPermissionText.font.pixelSize * 0.7
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.Wrap
2021-06-25 09:41:07 +02:00
//% "blueROCK needs to access your camera in order to scan QR-Codes. It will never record or store any photos or videos."
text: qsTrId("#cameraPermissionDeniedDetails")
}
2021-06-25 09:41:07 +02:00
Button {
id: grantPermissionButton
Layout.alignment: Layout.Center
//% "Allow access"
text: qsTrId("#allowAccess")
onClicked: control._requestCameraPermission()
}
Item {
Layout.fillHeight: true
}
}
}
QZXingFilter {
id: zxingFilter
decoder {
2021-06-25 09:41:07 +02:00
onTagFound: control._handleTag(tag)
enabledDecoders: QZXing.DecoderFormat_QR_CODE
}
}
Timer {
id: statusTextResetTimer
running: false
repeat: false
interval: 3000
2021-06-25 09:41:07 +02:00
onTriggered: _setDefaultStatusText()
}
}