6 required property var camera
7 required property real videoWidth
8 required property real videoHeight
10 // Drag origin in parent coordinates
11 property real _dragStartX: 0
12 property real _dragStartY: 0
13 property bool _dragging: false
14 property real _dragCurrentX: 0
15 property real _dragCurrentY: 0
17 readonly property bool _trackingEnabled: camera && camera.trackingEnabled
18 readonly property bool _canTrackPoint: _trackingEnabled && camera.supportsTrackingPoint
19 readonly property bool _canTrackRect: _trackingEnabled && camera.supportsTrackingRect
21 function mouseClicked(mouseX, mouseY) {
22 if (!_canTrackPoint) {
25 if (videoWidth <= 0 || videoHeight <= 0) {
28 // Click = point tracking
29 var marginH = (width - videoWidth) / 2
30 var marginV = (height - videoHeight) / 2
31 var nx = Math.max(Math.min((mouseX - marginH) / videoWidth, 1.0), 0.0)
32 var ny = Math.max(Math.min((mouseY - marginV) / videoHeight, 1.0), 0.0)
34 camera.startTrackingPoint(Qt.point(nx, ny), Math.min(pointRadius / videoWidth, 1.0))
37 function mouseDragStart(mouseX, mouseY) {
43 _dragCurrentX = mouseX
44 _dragCurrentY = mouseY
48 function mouseDragPositionChanged(mouseX, mouseY) {
52 _dragCurrentX = mouseX
53 _dragCurrentY = mouseY
56 function mouseDragEnd(mouseX, mouseY) {
62 if (videoWidth <= 0 || videoHeight <= 0) {
66 // Order coordinates: top-left and bottom-right
67 var x0 = Math.min(_dragStartX, mouseX)
68 var x1 = Math.max(_dragStartX, mouseX)
69 var y0 = Math.min(_dragStartY, mouseY)
70 var y1 = Math.max(_dragStartY, mouseY)
72 // Letterbox margins (black bars when aspect ratio doesn't match)
73 var marginH = (width - videoWidth) / 2
74 var marginV = (height - videoHeight) / 2
76 // Convert from view coordinates to video-relative coordinates
83 x0 = Math.max(Math.min(x0 / videoWidth, 1.0), 0.0)
84 x1 = Math.max(Math.min(x1 / videoWidth, 1.0), 0.0)
85 y0 = Math.max(Math.min(y0 / videoHeight, 1.0), 0.0)
86 y1 = Math.max(Math.min(y1 / videoHeight, 1.0), 0.0)
91 // Ignore degenerate rectangles (e.g. mostly-horizontal/vertical drags)
92 if (w < 0.01 || h < 0.01) {
98 // Drag = rectangle tracking
99 camera.startTrackingRect(Qt.rect(x0, y0, w, h))
105 // --- ROI selection overlay (green rectangle while dragging) ---
108 color: Qt.rgba(0.1, 0.85, 0.1, 0.25)
109 border.color: "green"
111 x: Math.min(_dragStartX, _dragCurrentX)
112 y: Math.min(_dragStartY, _dragCurrentY)
113 width: Math.abs(_dragCurrentX - _dragStartX)
114 height: Math.abs(_dragCurrentY - _dragStartY)
117 // --- Tracking status overlay (red rectangle/circle from camera feedback) ---
118 // Coordinates are normalized to the video frame (0.0–1.0). Convert to screen
119 // pixels by scaling by the displayed video size and offsetting by letterbox margins.
120 readonly property bool _trackingActive: _trackingEnabled && camera.trackingImageIsActive
121 readonly property bool _isPoint: _trackingActive && camera.trackingImageIsPoint
122 readonly property real _marginH: (rootItem.width - videoWidth) / 2
123 readonly property real _marginV: (rootItem.height - videoHeight) / 2
126 id: trackingStatusOverlay
130 radius: rootItem._isPoint ? width / 2 : 5
131 visible: rootItem._trackingActive
133 x: rootItem._trackingActive
134 ? (rootItem._isPoint ? rootItem._marginH + videoWidth * (camera.trackingImagePoint.x - camera.trackingImageRadius)
135 : rootItem._marginH + videoWidth * camera.trackingImageRect.x)
137 y: rootItem._trackingActive
138 ? (rootItem._isPoint ? rootItem._marginV + videoHeight * (camera.trackingImagePoint.y - camera.trackingImageRadius)
139 : rootItem._marginV + videoHeight * camera.trackingImageRect.y)
141 width: rootItem._trackingActive
142 ? (rootItem._isPoint ? videoWidth * camera.trackingImageRadius * 2
143 : videoWidth * camera.trackingImageRect.width)
145 height: rootItem._trackingActive
146 ? (rootItem._isPoint ? width
147 : videoHeight * camera.trackingImageRect.height)