/*!
* This file is part of CameraPlus.
*
- * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
+ * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-import QtQuick 1.1
+import QtQuick 2.0
import QtCamera 1.0
import CameraPlus 1.0
-// TODO: I've seen the reticle color changing to red while dragging it but failed to reproduce :(
+// TODO: hide all controls when we are focusing
+// TODO: hide all controls when we are dragging
+
MouseArea {
- property int cafStatus: AutoFocus.None
- property int status: AutoFocus.None
- id: mouse
+ id: mouse
+ x: renderArea.x
+ y: renderArea.y
+ width: renderArea.width
+ height: renderArea.height
+ drag.minimumX: 0
+ drag.minimumY: 0
+ drag.maximumX: width - reticle.width
+ drag.maximumY: height - reticle.height
- // A 100x100 central "rectangle"
- property variant centerRect: Qt.rect((mouse.width / 2 - 50), (mouse.height / 2) - 50, 100, 100);
+ property variant videoResolution
+ property variant renderArea
- property alias touchMode: reticle.touchMode
+ property bool locked: false
- x: cam.renderArea.x
- y: cam.renderArea.y
- width: cam.renderArea.width
- height: cam.renderArea.height
+ property int cafStatus: AutoFocus.None
+ property int status: AutoFocus.None
+ property Camera cam
+ property bool touchMode
- // Changing mode (which implies changing pages) will not reset ROI thus we do it here
- Component.onCompleted: cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
+ property variant touchPoint: Qt.point(mouse.width / 2, mouse.height / 2)
-/*
- // This is for debugging
- Rectangle {
- color: "blue"
- opacity: 0.2
- anchors.fill: parent
- }
+ // A 100x100 central "rectangle"
+ property variant centerRect: Qt.rect((mouse.width / 2 - 50), (mouse.height / 2) - 50, 100, 100)
- Rectangle {
- color: "red"
- opacity: 0.4
- x: centerRect.x
- y: centerRect.y
- width: centerRect.width
- height: centerRect.height
- }
-*/
- drag.target: reticle
- drag.axis: Drag.XandYAxis
- drag.minimumX: 0 - (0.1 * reticle.width)
- drag.minimumY: 0 - (0.1 * reticle.height)
- drag.maximumX: width - reticle.width + (0.1 * reticle.width)
- drag.maximumY: height - reticle.height + (0.1 * reticle.height)
-
- onStatusChanged: {
- if (status != AutoFocus.Running) {
- reticle.visible = true;
- }
- }
+ // ROI:
+ property variant primaryRoiRect: Qt.rect(0, 0, 0, 0)
+ property variant roiRects
+ property variant allRoiRects
+ property bool roiMode: allRoiRects != null && allRoiRects.length > 0 && !touchMode && !pressed
+
+ property variant __initialPos
+ onPressed: {
- function predictColor(caf, status) {
- if (status == AutoFocus.Success) {
- return "steelblue";
- }
- else if (status == AutoFocus.Fail) {
- return "red";
- }
- else if (status == AutoFocus.Running) {
- return "white";
- }
- else if (caf == AutoFocus.Success) {
- return "steelblue";
- }
- else {
- return "white";
- }
+ if (mouse.x >= reticle.x &&
+ mouse.y >= reticle.y &&
+ mouse.x <= reticle.x + reticle.width &&
+ mouse.y <= reticle.y + reticle.height) {
+ locked = true
}
- function moveReticle(x, y) {
- var xPos = x - ((reticle.width * 1) / 2);
- var yPos = y - ((reticle.height * 1) / 2);
- x = Math.min(Math.max(xPos, drag.minimumX), drag.maximumX);
- y = Math.min(Math.max(yPos, drag.minimumY), drag.maximumY);
- reticle.x = xPos;
- reticle.y = yPos;
+ __initialPos = touchPoint
+ calculateTouchPoint(mouse.x, mouse.y)
+ }
+
+ onReleased: {
+ calculateTouchPoint(mouse.x, mouse.y)
+ locked = false
+ }
+
+ onPositionChanged: calculateTouchPoint(mouse.x, mouse.y)
+ onCanceled: {
+ calculateTouchPoint(__initialPos.x, __initialPos.y)
+ locked = false
+ }
+
+ function resetReticle() {
+ calculateTouchPoint(centerRect.x, centerRect.y)
+ }
+
+ function setRegionOfInterest() {
+ if (!cam) {
+ // console.log("Cannot set ROI without camera object")
+ return
+ } else if (mouse.pressed) {
+ // console.log("Will not set ROI while pressed")
+ return
+ } else if (!touchMode && !roiMode) {
+ // console.log("resetting ROI")
+ if (cam.roi) {
+ cam.roi.resetRegionOfInterest()
+ }
+
+ return
}
- function moveToCenterIfNeeded(x, y) {
- if (x >= centerRect.x && y >= centerRect.y &&
- x <= centerRect.x + centerRect.width &&
- y <= centerRect.y + centerRect.height) {
- reticle.x = reticle.center.x
- reticle.y = reticle.center.y
- }
+ // TODO: rework this and move to unnormalized coordinates
+ // in terms of video resolution:
+ var rx = (videoResolution.width * reticle.x) / mouse.width
+ var rwidth = (videoResolution.width * reticle.width) / mouse.width
+ var ry = (videoResolution.height * reticle.y) / mouse.height
+ var rheight = (videoResolution.height * reticle.height) / mouse.height
+
+ // Translate to normalized coordinates (1x1 square) as expected by our C++ backend
+ rx = rx / videoResolution.width
+ rwidth = rwidth / videoResolution.width
+ ry = ry / videoResolution.height
+ rheight = rheight / videoResolution.height
+
+ // console.log("Setting ROI to: " + rx + "x" + ry)
+ cam.roi.setRegionOfInterest(Qt.rect(rx, ry, rwidth, rheight))
+ }
+
+ function calculateTouchPoint(x, y) {
+ if (x >= centerRect.x && y >= centerRect.y &&
+ x <= centerRect.x + centerRect.width &&
+ y <= centerRect.y + centerRect.height) {
+ touchMode = false
+ touchPoint = Qt.point(mouse.width / 2, mouse.height / 2)
+ return
}
- function setRegionOfInterest() {
- if (!reticle.touchMode) {
- cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
- return;
- }
+ touchMode = true
+ touchPoint = Qt.point(x, y)
+ }
- // take into account scale:
- var x = reticle.x + (reticle.width * 0.1);
- var y = reticle.y + (reticle.height * 0.1);
+ function predictColor(caf, status) {
+ if (status == AutoFocus.Success) {
+ return "steelblue"
+ } else if (status == AutoFocus.Fail) {
+ return "red"
+ } else if (status == AutoFocus.Running) {
+ return "white"
+ } else if (caf == AutoFocus.Success) {
+ return "steelblue"
+ } else {
+ return "white"
+ }
+ }
- var width = reticle.width * 0.8;
- var height = reticle.height * 0.8;
+ Repeater {
+ anchors.fill: parent
+ model: roiMode ? roiRects : 0
- // in terms of video resolution:
- x = (cam.videoResolution.width * x) / mouse.width;
- width = (cam.videoResolution.width * width) / mouse.width;
- y = (cam.videoResolution.height * y) / mouse.height;
- height = (cam.videoResolution.height * height) / mouse.height;
+ delegate: Rectangle {
+ x: modelData.x
+ y: modelData.y
+ width: modelData.width
+ height: modelData.height
+ color: "transparent"
+ border.color: "gray"
+ border.width: 2
+ }
+ }
- // Translate to normalized coordinates (1x1 square) as expected by our C++ backend
- x = x / cam.videoResolution.width;
- width = width / cam.videoResolution.width;
- y = y / cam.videoResolution.height;
- height = height / cam.videoResolution.height;
+ FocusRectangle {
+ id: reticle
+ width: mouse.pressed ? 150 : mouse.touchMode ? 200 : roiMode ? primaryRoiRect.width : 250
+ height: mouse.pressed ? 90 : mouse.touchMode ? 120 : roiMode ? primaryRoiRect.height : 150
+ x: Math.min(Math.max(mouse.touchPoint.x - (width / 2), drag.minimumX), drag.maximumX)
+ y: Math.min(Math.max(mouse.touchPoint.y - (height / 2), drag.minimumY), drag.maximumY)
+ color: predictColor(cafStatus, status)
- cam.autoFocus.setRegionOfInterest(Qt.rect(x, y, width, height));
+ onXChanged: setRegionOfInterest()
+ onYChanged: setRegionOfInterest()
+ /*
+ Behavior on x {
+ PropertyAnimation { duration: 100 }
+ enabled: !mouse.pressed
}
- onReleased: {
- moveToCenterIfNeeded(mouse.x, mouse.y);
- setRegionOfInterest();
+ Behavior on y {
+ PropertyAnimation { duration: 100 }
+ enabled: !mouse.pressed
+ }
+ */
+ Behavior on width {
+ PropertyAnimation { duration: 100 }
}
- onPressed: {
- moveReticle(mouse.x, mouse.y);
+ Behavior on height {
+ PropertyAnimation { duration: 100 }
}
- FocusRectangle {
- id: reticle
- property variant center: Qt.point((mouse.width - width) / 2, (mouse.height - height) / 2);
- property bool touchMode: !(reticle.x == center.x && reticle.y == center.y)
+ }
+
+ Connections {
+ target: settings
+ // Changing mode (which implies changing pages) will not reset ROI
+ // thus we do it here
+ onModeChanged: resetReticle()
+ }
- scale: mouse.pressed ? 0.6 : touchMode ? 0.8 : 1.0
+ Connections {
+ target: cam
+ onRunningChanged: resetReticle()
+ onVideoResolutionChanged: resetReticle()
+ }
- width: 250
- height: 150
- x: center.x
- y: center.y
+ Connections {
+ target: cam.roi
+ onRegionsChanged: {
+ allRoiRects = regions
+ primaryRoiRect = primary
+ roiRects = rest
- color: predictColor(cafStatus, status);
+ if (regions.length == 0) {
+ resetReticle()
+ return
+ }
+
+ touchPoint = Qt.point(primary.x + (reticle.width / 2),
+ primary.y + (reticle.height / 2))
}
+ }
+
+ /*
+ // This is for debugging
+ Rectangle {
+ color: "blue"
+ opacity: 0.2
+ anchors.fill: parent
+ }
- Timer {
- interval: 500
- running: status == AutoFocus.Running
- triggeredOnStart: true
- repeat: true
- onTriggered: reticle.visible = !reticle.visible
+ Rectangle {
+ color: "red"
+ opacity: 0.4
+ x: centerRect.x
+ y: centerRect.y
+ width: centerRect.width
+ height: centerRect.height
+ }
+ */
+ Timer {
+ interval: 500
+ running: status == AutoFocus.Running
+ triggeredOnStart: true
+ repeat: true
+ onTriggered: reticle.visible = !reticle.visible
+ onRunningChanged: {
+ if (!running) {
+ reticle.visible = true
+ }
}
+ }
}