AntiClipSettings/qml/DeviceView.qml

402 lines
16 KiB
QML
Raw Permalink Normal View History

2024-08-24 22:35:35 +08:00
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import AntiClipSettings 1.0
2024-08-13 20:06:10 +08:00
Item {
id: root
2024-08-21 09:26:06 +08:00
property alias enabled: shieldedRow.enabled
2024-08-14 20:01:38 +08:00
property int dargWidth: 12
2024-08-26 14:55:15 +08:00
property color openDoorAreaColor: "#0FF40D" // 绿色
2024-08-13 20:06:10 +08:00
property var openDoorAreaPoints: []
2024-08-16 16:24:15 +08:00
property int openDoorAreaWay: 0
2024-08-20 09:29:49 +08:00
property color shieldedAreaColor: "yellow"
2024-08-14 20:01:38 +08:00
property var shieldedAreaPoints: []
property bool shieldedAreaEnabled: false
property color antiClipAreaColor: "blue"
property var antiClipAreaPoints: []
property bool antiClipAreaEnabled: false
property alias flip: flipSwitch.checked
property alias videoRotation: rotateComboBox.currentIndex
2024-08-14 20:01:38 +08:00
Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: controlBar.top
Image {
id: image
anchors.centerIn: parent
cache: false
fillMode: Image.PreserveAspectFit
source: "image://videoframe/"
property real aspectRatio: 16 / 9
width: Math.min(parent.width, parent.height * aspectRatio)
height: width / aspectRatio
2024-08-21 09:26:06 +08:00
enabled: root.enabled
2024-08-13 20:06:10 +08:00
2024-08-14 20:01:38 +08:00
Canvas {
id: canvas
anchors.fill: parent
onPaint: {
2024-08-21 09:26:06 +08:00
2024-08-14 20:01:38 +08:00
var ctx = canvas.getContext("2d")
ctx.clearRect(0, 0, canvas.width, canvas.height)
2024-08-21 09:26:06 +08:00
if(!root.enabled)return
2024-08-16 16:24:15 +08:00
if(openDoorAreaWay == DeviceConnection.FullArea){
ctx.strokeStyle = openDoorAreaColor
ctx.lineWidth = 8
ctx.strokeRect(0,0, canvas.width,
canvas.height)
} else if ((openDoorAreaWay>=DeviceConnection.Quadrangle) &&(openDoorAreaPoints.length > 0)) {
2024-08-14 20:01:38 +08:00
ctx.strokeStyle = openDoorAreaColor
ctx.lineWidth = 2
2024-08-13 20:06:10 +08:00
2024-08-14 20:01:38 +08:00
ctx.beginPath()
let point = scaledPoint(openDoorAreaPoints[0],
width, height)
ctx.moveTo(point.x, point.y)
for (var i = 1; i < openDoorAreaPoints.length; i++) {
point = scaledPoint(openDoorAreaPoints[i],
width, height)
ctx.lineTo(point.x, point.y)
}
ctx.closePath()
ctx.stroke()
}
if (antiClipAreaEnabled && (antiClipAreaPoints.length > 0)) {
ctx.strokeStyle = antiClipAreaColor
ctx.lineWidth = 2
ctx.beginPath()
let point = scaledPoint(antiClipAreaPoints[0],
width, height)
ctx.moveTo(point.x, point.y)
for (var i = 1; i < antiClipAreaPoints.length; i++) {
point = scaledPoint(antiClipAreaPoints[i],
width, height)
ctx.lineTo(point.x, point.y)
}
ctx.closePath()
ctx.stroke()
}
if (shieldedAreaEnabled &&(shieldedAreaPoints.length > 0)) {
2024-08-16 16:24:15 +08:00
ctx.lineWidth = 2
ctx.strokeStyle = shieldedAreaColor
2024-08-14 20:01:38 +08:00
let point0 = scaledPoint(shieldedAreaPoints[0],
width, height)
let point1 = scaledPoint(shieldedAreaPoints[1],
width, height)
let point2 = scaledPoint(shieldedAreaPoints[2],
width, height)
let point3 = scaledPoint(shieldedAreaPoints[3],
width, height)
ctx.strokeRect(point0.x, point0.y, point1.x - point0.x,
point1.y - point0.y)
ctx.strokeRect(point2.x, point2.y, point3.x - point2.x,
point3.y - point2.y)
2024-08-13 20:06:10 +08:00
}
}
}
2024-08-14 20:01:38 +08:00
Repeater {
id: repeater
2024-08-16 16:24:15 +08:00
visible: openDoorAreaWay>=DeviceConnection.Quadrangle
2024-08-14 20:01:38 +08:00
model: openDoorAreaPoints
delegate: Rectangle {
width: dargWidth
height: dargWidth
2024-08-21 09:26:06 +08:00
visible: root.enabled &&(openDoorAreaWay>=DeviceConnection.Quadrangle)
2024-08-14 20:01:38 +08:00
color: openDoorAreaColor
x: scaledPoint(modelData, canvas.width,
canvas.height).x - width / 2
y: scaledPoint(modelData, canvas.width,
canvas.height).y - height / 2
}
2024-08-13 20:06:10 +08:00
}
2024-08-14 20:01:38 +08:00
Repeater {
id: shieldedAreaRepeater
model: shieldedAreaPoints
visible: shieldedAreaEnabled
delegate: Rectangle {
width: dargWidth
height: dargWidth
2024-08-21 09:26:06 +08:00
visible: root.enabled && shieldedAreaEnabled
2024-08-16 16:24:15 +08:00
color: shieldedAreaColor
2024-08-14 20:01:38 +08:00
x: scaledPoint(modelData, canvas.width,
canvas.height).x - width / 2
y: scaledPoint(modelData, canvas.width,
canvas.height).y - height / 2
}
2024-08-13 20:06:10 +08:00
}
2024-08-14 20:01:38 +08:00
Repeater {
id: antiAreaRepeater
visible: antiClipAreaEnabled
model: antiClipAreaPoints
delegate: Rectangle {
2024-08-21 09:26:06 +08:00
visible: root.enabled && antiClipAreaEnabled
2024-08-14 20:01:38 +08:00
width: dargWidth
height: dargWidth
color: antiClipAreaColor
x: scaledPoint(modelData, canvas.width,
canvas.height).x - width / 2
y: scaledPoint(modelData, canvas.width,
canvas.height).y - height / 2
}
2024-08-13 20:06:10 +08:00
}
2024-08-14 20:01:38 +08:00
MouseArea {
anchors.fill: parent
2024-08-21 09:26:06 +08:00
enabled: root.enabled
2024-08-14 20:01:38 +08:00
property int draggedOpenDoorAreaPointIndex: -1
property int draggedShieldedAreaPointIndex: -1
property int draggedAntiAreaPointIndex: -1
onPressed: mouse => {
2024-08-16 16:24:15 +08:00
if(openDoorAreaWay == DeviceConnection.Quadrangle){
2024-08-14 20:01:38 +08:00
for (var i = 0; i < openDoorAreaPoints.length; i++) {
let point = scaledPoint(
openDoorAreaPoints[i], canvas.width,
canvas.height)
if (isInside(mouse.x, mouse.y, point)) {
draggedOpenDoorAreaPointIndex = i
break
}
}
}
if (draggedOpenDoorAreaPointIndex >= 0)
return
if(shieldedAreaEnabled){
for (let i = 0; i < shieldedAreaPoints.length; i++) {
let point = scaledPoint(
shieldedAreaPoints[i], canvas.width,
canvas.height)
if (isInside(mouse.x, mouse.y, point)) {
draggedShieldedAreaPointIndex = i
break
}
}
}
if (draggedShieldedAreaPointIndex >= 0)
return
if(antiClipAreaEnabled){
for (let i = 0; i < antiClipAreaPoints.length; i++) {
let point = scaledPoint(
antiClipAreaPoints[i], canvas.width,
canvas.height)
if (isInside(mouse.x, mouse.y, point)) {
draggedAntiAreaPointIndex = i
break
}
}
}
}
onReleased: {
if (draggedOpenDoorAreaPointIndex >= 0) {
App.updateOpenDoorAreaPoints(openDoorAreaPoints)
draggedOpenDoorAreaPointIndex = -1
}
if (draggedShieldedAreaPointIndex >= 0) {
App.updateShieldedAreaPoints(shieldedAreaPoints)
draggedShieldedAreaPointIndex = -1
}
if (draggedAntiAreaPointIndex >= 0) {
App.updateAntiClipAreaPoints(antiClipAreaPoints)
draggedAntiAreaPointIndex = -1
}
}
onPositionChanged: mouse => {
if ((mouse.x < 0) || (mouse.x > canvas.width) || (mouse.y < 0) || (mouse.y > canvas.height)) return
if (draggedOpenDoorAreaPointIndex >= 0) {
openDoorAreaPoints[draggedOpenDoorAreaPointIndex]
= standardPoint(Qt.point(mouse.x, mouse.y), canvas.width, canvas.height)
canvas.requestPaint()
repeater.model = openDoorAreaPoints
} else if (draggedShieldedAreaPointIndex >= 0) {
shieldedAreaPoints[draggedShieldedAreaPointIndex]
= standardPoint(Qt.point(mouse.x,
mouse.y),
canvas.width,
canvas.height)
canvas.requestPaint()
shieldedAreaRepeater.model = shieldedAreaPoints
} else if (draggedAntiAreaPointIndex >= 0) {
antiClipAreaPoints[draggedAntiAreaPointIndex]
= standardPoint(Qt.point(mouse.x,
mouse.y),
canvas.width,
canvas.height)
canvas.requestPaint()
antiAreaRepeater.model = antiClipAreaPoints
}
2024-08-13 20:06:10 +08:00
}
2024-08-14 20:01:38 +08:00
function isInside(x, y, point) {
let edge = dargWidth / 2
return x >= point.x - edge && x <= point.x + edge
&& y >= point.y - edge && y <= point.y + edge
}
2024-08-13 20:06:10 +08:00
}
}
}
2024-08-16 16:24:15 +08:00
Grid {
2024-08-14 20:01:38 +08:00
id: controlBar
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
2024-08-16 16:24:15 +08:00
columns: 2
spacing: 10
2024-08-21 16:03:49 +08:00
verticalItemAlignment: Qt.AlignVCenter
Label { text: qsTr("图像: ") }
Row {
enabled: root.enabled
Label {
anchors.verticalCenter: parent.verticalCenter
text: qsTr("旋转")
}
Item {width: 10; height:10}
ComboBox {
id: rotateComboBox
model: ["0°","90°","180°","270°"]
onCurrentIndexChanged: {
App.currentDeviceRotation = rotateComboBox.currentIndex
}
}
Item {width: 70; height:10}
Label {
anchors.verticalCenter: parent.verticalCenter
text: qsTr("翻转")
}
Item {width: 10; height:10}
Switch {
id: flipSwitch
onToggled: App.currentDeviceFlip=flipSwitch.checked
}
}
2024-08-27 11:14:36 +08:00
Label {
2024-08-21 16:03:49 +08:00
text: qsTr("开门区域: ")
}
2024-08-16 16:24:15 +08:00
Row {
2024-08-21 09:26:06 +08:00
enabled: root.enabled
2024-08-16 16:24:15 +08:00
RadioButton {
text: "关闭"
checked: App.currentOpenDoorAreaWay ==DeviceConnection.Diabled
onToggled:{
App.currentOpenDoorAreaWay =DeviceConnection.Diabled
}
}
RadioButton {
text: "全区域"
checked: App.currentOpenDoorAreaWay ==DeviceConnection.FullArea
onToggled:{
App.currentOpenDoorAreaWay =DeviceConnection.FullArea
}
}
RadioButton {
text: "四边形"
checked: App.currentOpenDoorAreaWay ==DeviceConnection.Quadrangle
onToggled:{
App.currentOpenDoorAreaWay =DeviceConnection.Quadrangle
}
}
2024-08-14 20:01:38 +08:00
}
2024-08-16 16:24:15 +08:00
2024-08-27 11:14:36 +08:00
Label {text: qsTr("防夹区域: ")}
2024-08-16 16:24:15 +08:00
Row {
2024-08-21 09:26:06 +08:00
enabled: root.enabled
2024-08-16 16:24:15 +08:00
RadioButton {
text: "关闭"
checked: !App.currentAntiClipAreaEnabled
onToggled: {
App.currentAntiClipAreaEnabled=false
}
}
RadioButton {
text: "四边形"
checked: App.currentAntiClipAreaEnabled
onToggled: {
App.currentAntiClipAreaEnabled=true
}
}
2024-08-14 20:01:38 +08:00
}
2024-08-16 16:24:15 +08:00
2024-08-27 11:14:36 +08:00
Label {text: qsTr("屏蔽区域: ")}
2024-08-16 16:24:15 +08:00
Row {
id: shieldedRow
RadioButton {
checked: !shieldedAreaEnabled
text: "关闭"
onToggled: {
App.currentShieldedAreaEnabled = false
}
}
RadioButton {
checked: shieldedAreaEnabled
text: "开启"
onToggled: {
App.currentShieldedAreaEnabled = true
}
}
2024-08-14 20:01:38 +08:00
}
}
2024-08-16 16:24:15 +08:00
2024-08-13 20:06:10 +08:00
// 转换为显示画点
function scaledPoint(point, width, height) {
2024-08-16 16:24:15 +08:00
let x = point.x * width / App.DeviceWidth
let y = point.y * height / App.DeviceHeight
2024-08-13 20:06:10 +08:00
return Qt.point(x, y)
}
2024-08-14 20:01:38 +08:00
// 转换为设备画点(640x360)
2024-08-13 20:06:10 +08:00
function standardPoint(point, width, height) {
2024-08-16 16:24:15 +08:00
let x = point.x * App.DeviceWidth / width
let y = point.y * App.DeviceHeight / height
2024-08-13 20:06:10 +08:00
return Qt.point(x, y)
}
2024-08-21 09:26:06 +08:00
onEnabledChanged: {
canvas.requestPaint()
if(!enabled){
image.source = "image://videoframe/black"
}
}
2024-08-13 20:06:10 +08:00
Connections {
target: App
function onNewVideoFrame() {
image.source = ""
image.source = "image://videoframe/"
}
function onCurrentOpenDoorAreaPointsChanged() {
canvas.requestPaint()
2024-08-16 16:24:15 +08:00
repeater.model = openDoorAreaPoints
2024-08-13 20:06:10 +08:00
}
2024-08-14 20:01:38 +08:00
function onCurrentShieldedAreaPointsChanged() {
2024-08-20 09:29:49 +08:00
shieldedAreaRepeater.model = shieldedAreaPoints
2024-08-14 20:01:38 +08:00
canvas.requestPaint()
}
function onCurrentAntiClipAreaPointsChanged() {
2024-08-20 09:29:49 +08:00
antiAreaRepeater.model = antiClipAreaPoints
2024-08-14 20:01:38 +08:00
canvas.requestPaint()
}
2024-08-16 16:24:15 +08:00
function onCurrentOpenDoorAreaWayChanged(){
2024-08-14 20:01:38 +08:00
canvas.requestPaint()
}
function onCurrentShieldedAreaEnabledChanged(){
canvas.requestPaint()
}
function onCurrentAntiClipAreaEnabledChanged(){
canvas.requestPaint()
}
2024-08-13 20:06:10 +08:00
}
}