import QtQuick 2.0 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import QZXing 3.3 import QtMultimedia 5.12 import QtQuick.Shapes 1.12 import QtQuick.Controls.Material 2.12 import "../Components" Page { id: control property string _statusText: "" property string _statusColor: Material.primaryTextColor property bool _freezeScanning: false signal headerComponentChanged() //% "Scan QR-Code" title: qsTrId("#scanQrCode") onFocusChanged: focus ? open() : close() function open() { _setDefaultStatusText() control._freezeScanning = false if(serverConn.isCameraPermissionGranted()) cameraLoader.sourceComponent = cameraComponent else cameraLoader.sourceComponent = noPermissionComponent } function close() { cameraLoader.sourceComponent = null } function _setDefaultStatusText() { //% "Place the Code in the center" _statusText = qsTrId("#placeQrCodeInCenter") _statusColor = Material.primaryTextColor } 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 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 } } 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" 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 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 Layout.preferredWidth: parent.columnWidth Layout.alignment: Layout.Center font.pixelSize: app.landscape() ? parent.height * 0.25:parent.height * 0.15 font.family: fa5solid.name horizontalAlignment: Text.AlignHCenter text: "\uf3ed" } Label { id: noPermissionText Layout.preferredWidth: parent.columnWidth Layout.alignment: Layout.Center font.bold: true font.pixelSize: noPermissionIcon.height * 0.2 horizontalAlignment: Text.AlignHCenter wrapMode: Text.Wrap //% "Camera access required" text: qsTrId("#cameraPermissionDenied") } Label { id: noPermissionDetailText Layout.preferredWidth: parent.columnWidth Layout.alignment: Layout.Center font.pixelSize: noPermissionText.font.pixelSize * 0.7 horizontalAlignment: Text.AlignHCenter wrapMode: Text.Wrap //% "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") } Button { id: grantPermissionButton Layout.alignment: Layout.Center //% "Allow access" text: qsTrId("#allowAccess") onClicked: control._requestCameraPermission() } Item { Layout.fillHeight: true } } } QZXingFilter { id: zxingFilter decoder { onTagFound: control._handleTag(tag) enabledDecoders: QZXing.DecoderFormat_QR_CODE } } Timer { id: statusTextResetTimer running: false repeat: false interval: 3000 onTriggered: _setDefaultStatusText() } }