204 lines
5.5 KiB
QML
204 lines
5.5 KiB
QML
|
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()
|
||
|
}
|
||
|
}
|