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 //% "Scan QR-Code" title: qsTrId("#scanQrCode") standardButtons: Dialog.Cancel onOpened: { setDefaultStatusText() control._freezeScanning = false cameraLoader.sourceComponent = cameraComponent } onClosed: cameraLoader.sourceComponent = null function setDefaultStatusText() { //% "Place the Code in the center" _statusText = qsTrId("#placeQrCodeInCenter") _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 //% "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 } } enabledDecoders: QZXing.DecoderFormat_QR_CODE } } Timer { id: statusTextResetTimer running: false repeat: false interval: 3000 onTriggered: setDefaultStatusText() } }