implement QR code scanning
This commit is contained in:
@@ -1,25 +1,91 @@
|
||||
import QtQuick 2.6
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.0
|
||||
import QtMultimedia 5.6
|
||||
|
||||
Item {
|
||||
id: scanner
|
||||
|
||||
property bool active: false
|
||||
property string url
|
||||
property string scanData
|
||||
|
||||
property bool _pointsVisible
|
||||
|
||||
signal found
|
||||
|
||||
VideoOutput {
|
||||
id: vo
|
||||
anchors.fill: parent
|
||||
source: camera
|
||||
fillMode: VideoOutput.PreserveAspectCrop
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: (parent.height - parent.width) / 2
|
||||
anchors.top: parent.top
|
||||
color: Qt.rgba(0,0,0,0.5)
|
||||
}
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: (parent.height - parent.width) / 2
|
||||
anchors.bottom: parent.bottom
|
||||
color: Qt.rgba(0,0,0,0.5)
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
vo.grabToImage(function(result) {
|
||||
console.log("grab: image=" + (result.image !== undefined) + " url=" + result.url)
|
||||
if (result.image !== undefined) {
|
||||
console.log('scanning image for QR')
|
||||
QR.scanImage(result.image)
|
||||
}
|
||||
})
|
||||
Image {
|
||||
id: still
|
||||
anchors.fill: vo
|
||||
}
|
||||
|
||||
SequentialAnimation {
|
||||
id: foundAnimation
|
||||
PropertyAction { target: scanner; property: '_pointsVisible'; value: true}
|
||||
PauseAnimation { duration: 80 }
|
||||
PropertyAction { target: scanner; property: '_pointsVisible'; value: false}
|
||||
PauseAnimation { duration: 80 }
|
||||
PropertyAction { target: scanner; property: '_pointsVisible'; value: true}
|
||||
PauseAnimation { duration: 80 }
|
||||
PropertyAction { target: scanner; property: '_pointsVisible'; value: false}
|
||||
PauseAnimation { duration: 80 }
|
||||
PropertyAction { target: scanner; property: '_pointsVisible'; value: true}
|
||||
PauseAnimation { duration: 80 }
|
||||
PropertyAction { target: scanner; property: '_pointsVisible'; value: false}
|
||||
PauseAnimation { duration: 80 }
|
||||
PropertyAction { target: scanner; property: '_pointsVisible'; value: true}
|
||||
onFinished: found()
|
||||
}
|
||||
|
||||
Component {
|
||||
id: r
|
||||
Rectangle {
|
||||
property int cx
|
||||
property int cy
|
||||
width: 15
|
||||
height: 15
|
||||
x: cx - width/2
|
||||
y: cy - height/2
|
||||
radius: 5
|
||||
visible: scanner._pointsVisible
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: QR
|
||||
function onDataChanged() {
|
||||
console.log(QR.data)
|
||||
scanner.active = false
|
||||
scanner.scanData = QR.data
|
||||
still.source = scanner.url
|
||||
|
||||
var sx = still.width/still.sourceSize.width
|
||||
var sy = still.height/still.sourceSize.height
|
||||
r.createObject(scanner, {cx: QR.points[0].x * sx, cy: QR.points[0].y * sy, color: 'yellow'})
|
||||
r.createObject(scanner, {cx: QR.points[1].x * sx, cy: QR.points[1].y * sy, color: 'yellow'})
|
||||
r.createObject(scanner, {cx: QR.points[2].x * sx, cy: QR.points[2].y * sy, color: 'yellow'})
|
||||
r.createObject(scanner, {cx: QR.points[3].x * sx, cy: QR.points[3].y * sy, color: 'yellow'})
|
||||
|
||||
foundAnimation.start()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +94,12 @@ Item {
|
||||
deviceId: QtMultimedia.defaultCamera.deviceId
|
||||
viewfinder.resolution: "640x480"
|
||||
|
||||
focus {
|
||||
focusMode: Camera.FocusContinuous
|
||||
focusPointMode: Camera.FocusPointCustom
|
||||
customFocusPoint: Qt.point(0.5, 0.5)
|
||||
}
|
||||
|
||||
function dumpstats() {
|
||||
console.log(camera.viewfinder.resolution)
|
||||
console.log(camera.viewfinder.minimumFrameRate)
|
||||
@@ -36,6 +108,49 @@ Item {
|
||||
resolutions.forEach(function(item, i) {
|
||||
console.log('' + item.width + 'x' + item.height)
|
||||
})
|
||||
// TODO
|
||||
// pick a suitable resolution from the available resolutions
|
||||
// problem: some cameras have no supportedViewfinderResolutions
|
||||
// but still error out when an invalid resolution is set.
|
||||
// 640x480 seems to be universally available, but this needs to
|
||||
// be checked across a range of phone models.
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: scanTimer
|
||||
interval: 200
|
||||
repeat: true
|
||||
running: scanner.active
|
||||
onTriggered: {
|
||||
if (QR.busy)
|
||||
return
|
||||
vo.grabToImage(function(result) {
|
||||
if (result.image !== undefined) {
|
||||
scanner.url = result.url
|
||||
QR.scanImage(result.image)
|
||||
} else {
|
||||
console.log('image grab returned null')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
console.log('Scan page initialized')
|
||||
QtMultimedia.availableCameras.forEach(function(item) {
|
||||
console.log('cam found')
|
||||
console.log(item.deviceId)
|
||||
console.log(item.displayName)
|
||||
console.log(item.position)
|
||||
console.log(item.orientation)
|
||||
if (QtMultimedia.defaultCamera.deviceId == item.deviceId) {
|
||||
vo.orientation = item.orientation
|
||||
}
|
||||
|
||||
camera.dumpstats()
|
||||
})
|
||||
|
||||
active = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,25 @@ import QtQuick 2.6
|
||||
import QtQuick.Controls 2.0
|
||||
|
||||
Item {
|
||||
id: scanPage
|
||||
property string title: qsTr('Scan')
|
||||
|
||||
property bool toolbar: false
|
||||
|
||||
property string scanData
|
||||
|
||||
signal found
|
||||
|
||||
QRScan {
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
|
||||
onFound: {
|
||||
scanPage.scanData = scanData
|
||||
scanPage.found()
|
||||
app.stack.pop()
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
|
||||
@@ -80,7 +80,13 @@ Pane {
|
||||
|
||||
Button {
|
||||
text: qsTr('Scan QR Code')
|
||||
onClicked: app.stack.push(Qt.resolvedUrl('Scan.qml'))
|
||||
onClicked: {
|
||||
var page = app.stack.push(Qt.resolvedUrl('Scan.qml'))
|
||||
page.onFound.connect(function() {
|
||||
console.log('got ' + page.scanData)
|
||||
address.text = page.scanData
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user