Add missing capability.cpp
[harmattan/cameraplus] / qml / FocusReticle.qml
index 34d0329..39fba6b 100644 (file)
@@ -3,7 +3,7 @@
 /*!
  * 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
@@ -20,7 +20,7 @@
  * 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
 
@@ -28,187 +28,229 @@ import CameraPlus 1.0
 // TODO: hide all controls when we are dragging
 
 MouseArea {
-        property int cafStatus: AutoFocus.None
-        property int status: AutoFocus.None
-        property Camera cam: null
-        id: mouse
-
-        // A 100x100 central "rectangle"
-        property variant centerRect: Qt.rect((mouse.width / 2 - 50), (mouse.height / 2) - 50, 100, 100);
-
-        property alias touchMode: reticle.touchMode
-
-        x: cam ? cam.renderArea.x : 0
-        y: cam ? cam.renderArea.y : 0
-        width: cam ? cam.renderArea.width : 0
-        height: cam ? cam.renderArea.height : 0
-
-        Connections {
-                target: settings
-                // Changing mode (which implies changing pages) will not reset ROI
-                // thus we do it here
-                onModeChanged: {
-                        moveToCenter();
-                        cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
-                }
+    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
+
+    property variant videoResolution
+    property variant renderArea
+
+    property bool locked: false
+
+    property int cafStatus: AutoFocus.None
+    property int status: AutoFocus.None
+    property Camera cam
+    property bool touchMode
+
+    property variant touchPoint: Qt.point(mouse.width / 2, mouse.height / 2)
+
+    // A 100x100 central "rectangle"
+    property variant centerRect: Qt.rect((mouse.width / 2 - 50), (mouse.height / 2) - 50, 100, 100)
+
+    // 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: {
+
+        if (mouse.x >= reticle.x &&
+            mouse.y >= reticle.y &&
+            mouse.x <= reticle.x + reticle.width &&
+            mouse.y <= reticle.y + reticle.height) {
+            locked = true
         }
 
-        Connections {
-                target: cam
-                onRunningChanged: {
-                        if (cam.running) {
-                                setRegionOfInterest();
-                        }
-                }
-        }
-/*
-        // This is for debugging
-        Rectangle {
-                color: "blue"
-                opacity: 0.2
-                anchors.fill: parent
+        __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
         }
 
-        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;
-                }
+        // 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 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";
-                }
+        touchMode = true
+        touchPoint = Qt.point(x, y)
+    }
+
+    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"
         }
-
-        function moveToCenter() {
-                reticle.anchors.centerIn = reticle.parent;
-                reticle.touchMode = false;
+    }
+
+    Repeater {
+        anchors.fill: parent
+        model: roiMode ? roiRects : 0
+
+        delegate: Rectangle {
+            x: modelData.x
+            y: modelData.y
+            width: modelData.width
+            height: modelData.height
+            color: "transparent"
+            border.color: "gray"
+            border.width: 2
         }
-
-        function moveReticle(x, y) {
-                var xPos = x - ((reticle.width * 1) / 2);
-                var yPos = y - ((reticle.height * 1) / 2);
-                xPos = Math.min(Math.max(xPos, drag.minimumX), drag.maximumX);
-                yPos = Math.min(Math.max(yPos, drag.minimumY), drag.maximumY);
-                reticle.x = xPos;
-                reticle.y = yPos;
-                reticle.anchors.centerIn = undefined;
-                reticle.touchMode = true;
+    }
+
+    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)
+
+        onXChanged: setRegionOfInterest()
+        onYChanged: setRegionOfInterest()
+        /*
+        Behavior on x {
+            PropertyAnimation { duration: 100 }
+            enabled: !mouse.pressed
         }
 
-        function moveToCenterIfNeeded(x, y) {
-                if (x >= centerRect.x && y >= centerRect.y &&
-                    x <= centerRect.x + centerRect.width &&
-                    y <= centerRect.y + centerRect.height) {
-                        moveToCenter();
-                }
-                else {
-                        reticle.anchors.centerIn = undefined;
-                        reticle.touchMode = true;
-                }
+        Behavior on y {
+            PropertyAnimation { duration: 100 }
+            enabled: !mouse.pressed
         }
-
-        function setRegionOfInterest() {
-                if (!reticle.touchMode) {
-//                        console.log("resetting ROI");
-                        cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
-                        return;
-                }
-
-                // take into account scale:
-                var x = reticle.x + (reticle.width * 0.1);
-                var y = reticle.y + (reticle.height * 0.1);
-
-                var width = reticle.width * 0.8;
-                var height = reticle.height * 0.8;
-
-                // 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;
-
-                // 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;
-
-//                console.log("Setting ROI to: " + x + " " + y);
-                cam.autoFocus.setRegionOfInterest(Qt.rect(x, y, width, height));
+        */
+        Behavior on width {
+            PropertyAnimation { duration: 100 }
         }
 
-        onReleased: {
-                moveToCenterIfNeeded(mouse.x, mouse.y);
-                setRegionOfInterest();
+        Behavior on height {
+            PropertyAnimation { duration: 100 }
         }
 
-        onPressed: {
-                reticle.anchors.centerIn = undefined;
-                moveReticle(mouse.x, mouse.y);
+    }
+
+    Connections {
+        target: settings
+        // Changing mode (which implies changing pages) will not reset ROI
+        // thus we do it here
+        onModeChanged: resetReticle()
+    }
+
+    Connections {
+        target: cam
+        onRunningChanged: resetReticle()
+        onVideoResolutionChanged: resetReticle()
+    }
+
+    Connections {
+        target: cam.roi
+        onRegionsChanged: {
+            allRoiRects = regions
+            primaryRoiRect = primary
+            roiRects = rest
+
+            if (regions.length == 0) {
+                resetReticle()
+                return
+            }
+
+            touchPoint = Qt.point(primary.x + (reticle.width / 2),
+                primary.y + (reticle.height / 2))
         }
-
-        FocusRectangle {
-                id: reticle
-                property variant center: Qt.point((mouse.width - width) / 2, (mouse.height - height) / 2);
-                property bool touchMode: false
-
-                scale: mouse.pressed ? 0.6 : touchMode ? 0.8 : 1.0
-
-                width: 250
-                height: 150
-
-                anchors.centerIn: parent
-
-                color: predictColor(cafStatus, status);
-
-                Behavior on x {
-                        PropertyAnimation { duration: 100; }
-                }
-
-                Behavior on y {
-                        PropertyAnimation { duration: 100; }
-                }
-
-                Behavior on scale {
-                        PropertyAnimation { duration: 100; }
-                }
-        }
-
-        Timer {
-                interval: 500
-                running: status == AutoFocus.Running
-                triggeredOnStart: true
-                repeat: true
-                onTriggered: reticle.visible = !reticle.visible
+    }
+
+    /*
+    // This is for debugging
+    Rectangle {
+        color: "blue"
+        opacity: 0.2
+        anchors.fill: parent
+    }
+
+    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
+            }
         }
+    }
 }