--- /dev/null
+// -*- qml -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+import QtQuick 1.1
+import com.nokia.meego 1.1
+import QtCamera 1.0
+import CameraPlus 1.0
+
+Item {
+ anchors.fill: parent
+ id: page
+
+ property int policyMode: CameraResources.None
+
+ property Camera cam: null
+ property Item dimmer: null
+ property ControlsActivationData activationData: ControlsActivationData {}
+ property bool controlsVisible: cam.running && !standby.visible
+ property bool focusReticleVisible: true
+ property bool enableViewfinder: true
+
+ property alias previewAnimationRunning: preview.animationRunning
+
+ signal batteryLow
+
+ function cameraError() {
+ // Nothing
+ }
+
+ function policyLost() {
+ // Nothing
+ }
+
+ onStatusChanged: {
+// TODO:
+ if (status == PageStatus.Activating && enableViewfinder) {
+ cam.renderingEnabled = true
+ }
+ else if (status == PageStatus.Active) {
+ focusReticle.resetReticle()
+
+ if (!enableViewfinder) {
+ cam.renderingEnabled = false
+ }
+ }
+ }
+
+ ModeButton {
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ anchors.rightMargin: 20
+ anchors.bottomMargin: 20
+ visible: controlsVisible && activationData.modeSelectorVisible
+ }
+
+}
import com.nokia.meego 1.1
Column {
- id: col
- spacing: 10
+ id: col
+ spacing: 10
+ width: parent.width
+
+ Label {
+ font.pixelSize: 36
+ text: qsTr("Camera settings")
width: parent.width
+ }
+
+ TextSwitch {
+ text: qsTr("Show grid lines")
+
+ // We have to do it that way because QML complains about a binding
+ // loop for checked if we bind the checked property to the settings value.
+ Component.onCompleted: checked = settings.gridEnabled
+
+ onCheckedChanged: settings.gridEnabled = checked
+ }
- Label {
- font.pixelSize: 36
- text: qsTr("Camera settings");
- width: parent.width
- }
-
- TextSwitch {
- text: qsTr("Show grid lines");
-
- // We have to do it that way because QML complains about a binding
- // loop for checked if we bind the checked property to the settings value.
- Component.onCompleted: checked = settings.gridEnabled;
-
- onCheckedChanged: settings.gridEnabled = checked;
- }
-
- SectionHeader {
- text: qsTr("Creator name");
- width: parent.width
- }
-
- TextField {
- placeholderText: qsTr("Name or copyright");
- width: parent.width
- text: settings.creatorName
- onTextChanged: settings.creatorName = text;
- }
-
- TextSwitch {
- text: qsTr("Use zoom keys for capture");
-
- // We have to do it that way because QML complains about a binding
- // loop for checked if we bind the checked property to the settings value.
- Component.onCompleted: checked = settings.zoomAsShutter;
- onCheckedChanged: settings.zoomAsShutter = checked;
- }
-
- TextSwitch {
- text: qsTr("Enable camera sounds");
-
- // We have to do it that way because QML complains about a binding
- // loop for checked if we bind the checked property to the settings value.
- Component.onCompleted: checked = settings.soundEnabled;
- onCheckedChanged: settings.soundEnabled = checked;
- }
-
- TextSwitch {
- id: useGps
- text: qsTr("Use GPS");
-
- // We have to do it that way because QML complains about a binding
- // loop for checked if we bind the checked property to the settings value.
- Component.onCompleted: checked = settings.useGps;
- onCheckedChanged: settings.useGps = checked;
- }
-
- TextSwitch {
- // TODO: transition when hiding/showing and we should scroll a bit to show it
- visible: useGps.checked
-
- text: qsTr("Use geotags");
-
- // We have to do it that way because QML complains about a binding
- // loop for checked if we bind the checked property to the settings value.
- Component.onCompleted: checked = settings.useGeotags;
- onCheckedChanged: settings.useGeotags = checked;
- }
+ SectionHeader {
+ text: qsTr("Creator name")
+ width: parent.width
+ }
+
+ TextField {
+ placeholderText: qsTr("Name or copyright")
+ width: parent.width
+ text: settings.creatorName
+ onTextChanged: settings.creatorName = text
+ }
+
+ TextSwitch {
+ text: qsTr("Use zoom keys for capture")
+
+ // We have to do it that way because QML complains about a binding
+ // loop for checked if we bind the checked property to the settings value.
+ Component.onCompleted: checked = settings.zoomAsShutter
+ onCheckedChanged: settings.zoomAsShutter = checked
+ }
+
+ TextSwitch {
+ text: qsTr("Enable camera sounds")
+
+ // We have to do it that way because QML complains about a binding
+ // loop for checked if we bind the checked property to the settings value.
+ Component.onCompleted: checked = settings.soundEnabled
+ onCheckedChanged: settings.soundEnabled = checked
+ }
+
+ TextSwitch {
+ id: useGps
+ text: qsTr("Use GPS")
+
+ // We have to do it that way because QML complains about a binding
+ // loop for checked if we bind the checked property to the settings value.
+ Component.onCompleted: checked = settings.useGps
+ onCheckedChanged: settings.useGps = checked
+ }
+
+ TextSwitch {
+ // TODO: transition when hiding/showing and we should scroll a bit to show it
+ visible: useGps.checked
+
+ text: qsTr("Use geotags")
+
+ // We have to do it that way because QML complains about a binding
+ // loop for checked if we bind the checked property to the settings value.
+ Component.onCompleted: checked = settings.useGeotags
+ onCheckedChanged: settings.useGeotags = checked
+ }
}
import "CameraToolBar.js" as Layout
Rectangle {
- id: tools
- property bool expanded: false
- property list<Item> items
- property int targetWidth: parent.width - (2 * anchors.leftMargin)
- property alias menuWidth: menu.width
- property bool manualBack: false
- signal clicked
+ id: tools
+ property bool expanded: false
+ property list<Item> items
+ property int targetWidth: parent.width - (2 * anchors.leftMargin)
+ property alias menuWidth: menu.width
+ property bool manualBack: false
+ signal clicked
- height: menu.height
- width: expanded ? targetWidth : menu.width
- color: expanded ? "black" : width == menu.width ? "transparent" : "black"
- border.color: expanded ? "gray" : width == menu.width ? "transparent" : "gray"
- radius: 20
+ height: menu.height
+ width: expanded ? targetWidth : menu.width
+ color: expanded ? "black" : width == menu.width ? "transparent" : "black"
+ border.color: expanded ? "gray" : width == menu.width ? "transparent" : "gray"
+ radius: 20
- Behavior on width {
- PropertyAnimation { duration: 100; }
- }
-
- ToolIcon {
- property bool __isMenu: true
- id: menu
- anchors.verticalCenter: parent.verticalCenter
- iconSource: "image://theme/icon-m-toolbar-back-white"
- onClicked: {
- if (tools.manualBack) {
- tools.clicked();
- return;
- }
+ Behavior on width {
+ PropertyAnimation { duration: 100 }
+ }
- if (!expanded) {
- expanded = true;
- }
- else if (Layout.stack.length == 1) {
- expanded = false;
- }
- else {
- Layout.pop();
- }
- }
+ ToolIcon {
+ property bool __isMenu: true
+ id: menu
+ anchors.verticalCenter: parent.verticalCenter
+ iconSource: "image://theme/icon-m-toolbar-back-white"
+ onClicked: {
+ if (tools.manualBack) {
+ tools.clicked()
+ return
+ }
- anchors.left: parent.left
- rotation: 180
+ if (!expanded) {
+ expanded = true
+ } else if (Layout.stack.length == 1) {
+ expanded = false
+ } else {
+ Layout.pop()
+ }
}
- onExpandedChanged: {
- if (tools.expanded) {
- tools.push(tools.items);
- }
- else {
- tools.pop();
- }
+ anchors.left: parent.left
+ rotation: 180
+ }
+
+ onExpandedChanged: {
+ if (tools.expanded) {
+ tools.push(tools.items)
+ } else {
+ tools.pop()
}
+ }
- onWidthChanged: Layout.layout();
- onTargetWidthChanged: Layout.layout();
+ onWidthChanged: Layout.layout()
+ onTargetWidthChanged: Layout.layout()
- function push(items) {
- return Layout.push(items);
- }
+ function push(items) {
+ return Layout.push(items)
+ }
- function pop() {
- return Layout.pop();
- }
+ function pop() {
+ return Layout.pop()
+ }
- state: "collapsed"
- states: [
+ state: "collapsed"
+ states: [
State {
- name: "expanded"
- when: tools.expanded
+ name: "expanded"
+ when: tools.expanded
},
State {
- name: "collapsed"
- when: !tools.expanded
+ name: "collapsed"
+ when: !tools.expanded
}
- ]
+ ]
- transitions: [
+ transitions: [
Transition {
- from: "expanded"
- to: "collapsed"
+ from: "expanded"
+ to: "collapsed"
- PropertyAnimation {
- property: "rotation"
- target: menu
- from: 0
- to: 180
- duration: 500
- }
+ PropertyAnimation {
+ property: "rotation"
+ target: menu
+ from: 0
+ to: 180
+ duration: 500
+ }
},
Transition {
- from: "collapsed"
- to: "expanded"
- PropertyAnimation {
- property: "rotation"
- target: menu
- from: 180
- to: 360
- duration: 500
- }
+ from: "collapsed"
+ to: "expanded"
+ PropertyAnimation {
+ property: "rotation"
+ target: menu
+ from: 180
+ to: 360
+ duration: 500
+ }
}
- ]
+ ]
}
--- /dev/null
+// -*- qml -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+import QtQuick 1.1
+import QtCamera 1.0
+import CameraPlus 1.0
+
+Camera {
+ id: cam
+
+ property bool pressed: loader.item ? loader.item.pressed : false
+ property int policyMode: loader.item ? loader.item.policyMode : CameraResources.None
+
+ renderingEnabled: mainView.currentItem == cam
+
+ function policyLost() {
+ if (loader.item) {
+ loader.item.policyLost()
+ }
+ }
+
+ function checkBattery() {
+ // We are fine if we are connected to the charger:
+ if (batteryMonitor.charging) {
+ return true
+ }
+
+ // If we have enough battery then we are fine:
+ if (!batteryMonitor.critical) {
+ return true
+ }
+
+ return false
+ }
+
+ Component.onDestruction: cam.stop()
+
+ onRunningChanged: {
+ if (!cam.running) {
+ mountProtector.unlock()
+ }
+ }
+
+ notifications: Sounds {
+ id: sounds
+ mute: !settings.soundEnabled
+ }
+
+ BatteryInfo {
+ id: batteryMonitor
+ active: cam.running
+
+ function check() {
+ if (!checkBattery()) {
+ loader.item.batteryLow()
+ }
+ }
+
+ onChargingChanged: {
+ batteryMonitor.check()
+ }
+
+ onCriticalChanged: {
+ batteryMonitor.check()
+ }
+ }
+
+ PreviewImage {
+ id: preview
+ }
+
+ Connections {
+ target: loader.item
+ onPreviewAvailable: preview.setPreview(uri)
+ }
+
+ Binding {
+ target: loader.item
+ property: "cam"
+ value: cam
+ when: loader.item != null
+ }
+
+ Binding {
+ target: loader.item
+ property: "animationRunning"
+ value: preview.animationRunning
+ when: loader.item != null
+ }
+
+ onRoiChanged: roi.normalize = false
+
+ GridLines {
+ x: cam.renderArea.x
+ y: cam.renderArea.y
+ width: cam.renderArea.width
+ height: cam.renderArea.height
+ visible: settings.gridEnabled
+ }
+
+ FocusReticle {
+ id: focusReticle
+ cam: cam
+ visible: loader.item != null && loader.item.controlsVisible &&
+ cam.autoFocus.canFocus(cam.scene.value)
+ cafStatus: cam ? cam.autoFocus.cafStatus : -1
+ status: cam ? cam.autoFocus.status : -1
+ }
+
+ Loader {
+ id: loader
+ property string src: mode == Camera.VideoMode ? "VideoOverlay.qml" : "ImageOverlay.qml"
+ anchors.fill: parent
+ source: Qt.resolvedUrl(src)
+ }
+
+ Binding {
+ target: cam.flash
+ property: "value"
+ when: cam.mode == Camera.ImageMode
+ value: settings.imageFlashMode
+ }
+
+ Binding {
+ target: settings
+ property: "imageFlashMode"
+ when: cam.mode == Camera.ImageMode
+ value: cam.flash.value
+ }
+
+ Binding {
+ target: cam.scene
+ property: "value"
+ when: cam.mode == Camera.VideoMode
+ value: settings.videoSceneMode
+ }
+
+ Binding {
+ target: cam.scene
+ property: "value"
+ when: cam.mode == Camera.ImageMode
+ value: settings.imageSceneMode
+ }
+
+ Binding {
+ target: cam.evComp
+ property: "value"
+ when: cam.mode == Camera.ImageMode
+ value: settings.imageEvComp
+ }
+
+ Binding {
+ target: cam.evComp
+ property: "value"
+ when: cam.mode == Camera.VideoMode
+ value: settings.videoEvComp
+ }
+
+ Binding {
+ target: settings
+ property: "imageEvComp"
+ when: cam.mode == Camera.ImageMode
+ value: cam.evComp.value
+ }
+
+ Binding {
+ target: settings
+ property: "videoEvComp"
+ when: cam.mode == Camera.VideoMode
+ value: cam.evComp.value
+ }
+
+ Binding {
+ target: cam.whiteBalance
+ property: "value"
+ when: cam.mode == Camera.ImageMode
+ value: settings.imageWhiteBalance
+ }
+
+ Binding {
+ target: cam.whiteBalance
+ property: "value"
+ when: cam.mode == Camera.VideoMode
+ value: settings.videoWhiteBalance
+ }
+
+ Binding {
+ target: cam.colorTone
+ property: "value"
+ when: cam.mode == Camera.ImageMode
+ value: settings.imageColorFilter
+ }
+
+ Binding {
+ target: cam.colorTone
+ property: "value"
+ when: cam.mode == Camera.VideoMode
+ value: settings.videoColorFilter
+ }
+
+ Binding {
+ target: cam.iso
+ property: "value"
+ when: cam.mode == Camera.ImageMode
+ value: settings.imageIso
+ }
+
+ Binding {
+ target: settings
+ property: "imageIso"
+ when: cam.mode == Camera.ImageMode
+ value: cam.iso.value
+ }
+
+ Binding {
+ target: cam.videoMute
+ property: "enabled"
+ value: settings.videoMuted
+ }
+
+ Binding {
+ target: cam.roi
+ property: "enabled"
+ value: settings.faceDetectionEnabled && !focusReticle.pressed && !focusReticle.touchMode && cam.mode == Camera.ImageMode
+ }
+
+ onError: {
+ if (pipelineManager.error) {
+ // Ignore any subsequent errors.
+ // Killing pulseaudio while recording will lead to an
+ // infinite supply of errors which will break the UI
+ // if we show a banner for each.
+ return
+ }
+
+ pipelineManager.error = true
+ if (loader.item) {
+ loader.item.cameraError()
+ }
+
+ console.log("Camera error (" + code + "): " + message + " " + debug)
+ showError(qsTr("Camera error. Please restart the application."))
+ // We cannot stop camera here. Seems there is a race condition somewhere
+ // which leads to a freeze if we do so.
+ }
+
+}
import com.nokia.meego 1.1
Item {
- id: button
+ id: button
- property url iconSource
- property Style platformStyle: ButtonStyle {}
+ property url iconSource
+ property Style platformStyle: ButtonStyle {}
- property alias pressed: mouse.pressed
- property alias containsMouse: mouse.containsMouse
- property alias mouseX: mouse.mouseX
- property alias mouseY: mouse.mouseY
+ property alias pressed: mouse.pressed
+ property alias mouseX: mouse.mouseX
+ property alias mouseY: mouse.mouseY
- signal clicked
- signal exited
+ signal clicked
+ signal exited
- MouseArea {
- id: mouse
- anchors.fill: parent
- onClicked: button.clicked();
- onExited: button.exited();
- }
+ MouseArea {
+ id: mouse
+ anchors.fill: parent
+ onClicked: button.clicked()
+ onExited: button.exited()
+ }
- BorderImage {
- id: background
- anchors.fill: parent
- border.left: button.platformStyle.backgroundMarginLeft
- border.top: button.platformStyle.backgroundMarginTop
- border.right: button.platformStyle.backgroundMarginRight
- border.bottom: button.platformStyle.backgroundMarginBottom
- source: pressed ? button.platformStyle.pressedBackground : button.platformStyle.background
- }
+ BorderImage {
+ id: background
+ anchors.fill: parent
+ border.left: button.platformStyle.backgroundMarginLeft
+ border.top: button.platformStyle.backgroundMarginTop
+ border.right: button.platformStyle.backgroundMarginRight
+ border.bottom: button.platformStyle.backgroundMarginBottom
+ source: pressed ? button.platformStyle.pressedBackground : button.platformStyle.background
+ }
- Image {
- id: icon
- anchors.centerIn: parent
- anchors.verticalCenter: parent.verticalCenter
- anchors.verticalCenterOffset: -1
- source: button.iconSource
- visible: source != ""
- }
+ Image {
+ id: icon
+ anchors.centerIn: parent
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenterOffset: -1
+ source: button.iconSource
+ visible: source != ""
+ }
}
\ No newline at end of file
// TODO: hide all controls when we are dragging
MouseArea {
- id: mouse
- x: cam ? cam.renderArea.x : 0
- y: cam ? cam.renderArea.y : 0
- width: cam ? cam.renderArea.width : 0
- height: cam ? cam.renderArea.height : 0
- drag.minimumX: 0
- drag.minimumY: 0
- drag.maximumX: width - reticle.width
- drag.maximumY: height - reticle.height
-
- 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
-
- onPressed: calculateTouchPoint(mouse.x, mouse.y);
- onReleased: calculateTouchPoint(mouse.x, mouse.y);
- onPositionChanged: calculateTouchPoint(mouse.x, mouse.y);
-
- function resetReticle() {
- calculateTouchPoint(centerRect.x, centerRect.y)
+ id: mouse
+ x: cam ? cam.renderArea.x : 0
+ y: cam ? cam.renderArea.y : 0
+ width: cam ? cam.renderArea.width : 0
+ height: cam ? cam.renderArea.height : 0
+ drag.minimumX: 0
+ drag.minimumY: 0
+ drag.maximumX: width - reticle.width
+ drag.maximumY: height - reticle.height
+
+ 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
+
+ onPressed: calculateTouchPoint(mouse.x, mouse.y)
+ onReleased: calculateTouchPoint(mouse.x, mouse.y)
+ onPositionChanged: calculateTouchPoint(mouse.x, mouse.y)
+
+ 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")
+ cam.roi.resetRegionOfInterest()
+ return
}
- function setRegionOfInterest() {
- if (!cam) {
-// console.log("Cannot set ROI without camera object");
- return;
- }
-
- if (mouse.pressed) {
-// console.log("Will not set ROI while pressed");
- return;
- }
-
- if (!touchMode && !roiMode) {
-// console.log("resetting ROI");
- cam.roi.resetRegionOfInterest();
- return;
- }
-
-// TODO: rework this and move to unnormalized coordinates
- // in terms of video resolution:
- var rx = (cam.videoResolution.width * reticle.x) / mouse.width;
- var rwidth = (cam.videoResolution.width * reticle.width) / mouse.width;
- var ry = (cam.videoResolution.height * reticle.y) / mouse.height;
- var rheight = (cam.videoResolution.height * reticle.height) / mouse.height;
-
- // Translate to normalized coordinates (1x1 square) as expected by our C++ backend
- rx = rx / cam.videoResolution.width;
- rwidth = rwidth / cam.videoResolution.width;
- ry = ry / cam.videoResolution.height;
- rheight = rheight / cam.videoResolution.height;
-
-// console.log("Setting ROI to: " + rx + "x" + ry);
- cam.roi.setRegionOfInterest(Qt.rect(rx, ry, rwidth, rheight));
+ // TODO: rework this and move to unnormalized coordinates
+ // in terms of video resolution:
+ var rx = (cam.videoResolution.width * reticle.x) / mouse.width
+ var rwidth = (cam.videoResolution.width * reticle.width) / mouse.width
+ var ry = (cam.videoResolution.height * reticle.y) / mouse.height
+ var rheight = (cam.videoResolution.height * reticle.height) / mouse.height
+
+ // Translate to normalized coordinates (1x1 square) as expected by our C++ backend
+ rx = rx / cam.videoResolution.width
+ rwidth = rwidth / cam.videoResolution.width
+ ry = ry / cam.videoResolution.height
+ rheight = rheight / cam.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 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;
- }
-
- touchMode = true;
- touchPoint = Qt.point(x, y)
+ 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 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";
- }
+ }
+
+ 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
}
-
- 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
- }
+ }
+
+ 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
}
- 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
- }
-
- Behavior on y {
- PropertyAnimation { duration: 100; }
- enabled: !mouse.pressed
- }
-*/
- Behavior on width {
- PropertyAnimation { duration: 100; }
- }
-
- Behavior on height {
- PropertyAnimation { duration: 100; }
- }
-
+ Behavior on y {
+ PropertyAnimation { duration: 100 }
+ enabled: !mouse.pressed
}
-
- Connections {
- target: settings
- // Changing mode (which implies changing pages) will not reset ROI
- // thus we do it here
- onModeChanged: resetReticle();
+ */
+ Behavior on width {
+ PropertyAnimation { duration: 100 }
}
- 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));
- }
- }
-/*
- // This is for debugging
- Rectangle {
- color: "blue"
- opacity: 0.2
- anchors.fill: parent
+ Behavior on height {
+ PropertyAnimation { duration: 100 }
}
- Rectangle {
- color: "red"
- opacity: 0.4
- x: centerRect.x
- y: centerRect.y
- width: centerRect.width
- height: centerRect.height
+ }
+
+ 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))
}
-*/
- Timer {
- interval: 500
- running: status == AutoFocus.Running
- triggeredOnStart: true
- repeat: true
- onTriggered: reticle.visible = !reticle.visible
- onRunningChanged: {
- if (!running) {
- reticle.visible = true;
- }
- }
+ }
+
+ /*
+ // 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
+ }
}
+ }
}
--- /dev/null
+// -*- qml -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+import QtQuick 1.1
+import com.nokia.meego 1.1
+import QtCamera 1.0
+import CameraPlus 1.0
+import "data.js" as Data
+
+Item {
+ id: overlay
+
+ property Camera cam
+ property bool animationRunning: false
+ property int policyMode: CameraResources.Image
+ property bool pressed: capture.pressed || zoomSlider.pressed || modeButton.pressed
+ property bool controlsVisible: imageMode.canCapture && cam.running && !animationRunning
+ && dimmer.opacity == 0.0 && !cameraMode.busy
+
+ signal previewAvailable(string uri)
+
+ anchors.fill: parent
+
+ ImageMode {
+ id: imageMode
+ camera: cam
+ onPreviewAvailable: {
+ overlay.previewAvailable(preview)
+ cam.autoFocus.stopAutoFocus()
+ }
+
+ onSaved: mountProtector.unlock()
+ }
+
+ ZoomSlider {
+ id: zoomSlider
+ camera: cam
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ anchors.horizontalCenter: parent.horizontalCenter
+ visible: controlsVisible
+ }
+
+ ModeButton {
+ id: modeButton
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ anchors.rightMargin: 20
+ anchors.bottomMargin: 20
+ visible: controlsVisible
+ }
+
+ CaptureButton {
+ id: capture
+ anchors.right: parent.right
+ anchors.rightMargin: 20
+ anchors.verticalCenter: parent.verticalCenter
+ iconSource: "image://theme/icon-m-camera-shutter"
+ width: 75
+ height: 75
+ opacity: 0.5
+ onClicked: captureImage()
+ visible: controlsVisible && (!settings.zoomAsShutter && keys.active)
+
+ onExited: {
+ if (mouseX <= 0 || mouseY <= 0 || mouseX > width || mouseY > height) {
+ // Release outside the button:
+ cam.autoFocus.stopAutoFocus()
+ }
+ }
+ }
+
+ Timer {
+ id: autoFocusTimer
+ interval: 200
+ running: capture.pressed || zoomCapture.zoomPressed
+ repeat: false
+ onTriggered: {
+ if (cam.autoFocus.cafStatus != AutoFocus.Success) {
+ cam.autoFocus.startAutoFocus()
+ }
+ }
+ }
+
+ ZoomCaptureButton {
+ id: zoomCapture
+ onReleased: parent.captureImage()
+ }
+
+ ZoomCaptureCancel {
+ anchors.fill: parent
+ zoomCapture: zoomCapture
+ onCanceled: {
+ if (!autoFocusTimer.running) {
+ cam.autoFocus.stopAutoFocus()
+ }
+ }
+ }
+
+ CameraToolBar {
+ id: toolBar
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 20
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ opacity: 0.5
+ targetWidth: parent.width - (anchors.leftMargin * 2) - (66 * 1.5)
+ visible: controlsVisible
+ expanded: settings.showToolBar
+ onExpandedChanged: settings.showToolBar = expanded
+ items: [
+ FlashButton {
+ onClicked: toolBar.push(items)
+ },
+ ImageSceneButton {
+ onClicked: toolBar.push(items)
+ },
+ ImageEvCompButton {
+ onClicked: toolBar.push(items)
+ },
+ ImageWhiteBalanceButton {
+ onClicked: toolBar.push(items)
+ },
+ ImageColorFilterButton {
+ onClicked: toolBar.push(items)
+ },
+ ImageIsoButton {
+ onClicked: toolBar.push(items)
+ }
+ ]
+ }
+
+ Rectangle {
+ id: indicators
+ anchors.top: parent.top
+ anchors.topMargin: 20
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ width: 48
+ height: col.height
+ color: "black"
+ border.color: "gray"
+ radius: 20
+ opacity: 0.5
+ visible: controlsVisible
+
+ Column {
+ id: col
+ width: parent.width
+ spacing: 5
+
+ Indicator {
+ id: resolutionIndicator
+ source: "image://theme/" + Data.imageIcon(settings.imageAspectRatio, settings.imageResolution)
+ }
+
+ Indicator {
+ id: wbIndicator
+ source: visible ? "image://theme/" + Data.wbIcon(settings.imageWhiteBalance) + "-screen" : ""
+ visible: settings.imageWhiteBalance != WhiteBalance.Auto
+ }
+
+ Indicator {
+ id: cfIndicator
+ source: "image://theme/" + Data.cfIcon(settings.imageColorFilter) + "-screen"
+ visible: settings.imageColorFilter != ColorTone.Normal
+ }
+
+ Indicator {
+ id: isoIndicator
+ visible: settings.imageIso != 0
+ source: "image://theme/" + Data.isoIcon(settings.imageIso)
+ }
+
+ Indicator {
+ id: gpsIndicator
+ visible: settings.useGps
+ source: "image://theme/icon-m-camera-location"
+
+ PropertyAnimation on opacity {
+ easing.type: Easing.OutSine
+ loops: Animation.Infinite
+ from: 0.2
+ to: 1.0
+ duration: 1000
+ running: settings.useGps && !positionSource.position.longitudeValid
+ alwaysRunToEnd: true
+ }
+ }
+
+ Indicator {
+ id: faceDetectionIndicator
+ visible: settings.faceDetectionEnabled
+ source: "image://theme/icon-m-camera-face-detection-screen"
+ }
+
+ }
+ }
+
+ function cameraError() {
+ mountProtector.unlock()
+ }
+
+ function policyLost() {
+ // Nothing
+ }
+
+ function batteryLow() {
+ // Nothing
+ }
+
+ function captureImage() {
+ if (!imageMode.canCapture) {
+ showError(qsTr("Camera is already capturing an image."))
+ } else if (!checkBattery()) {
+ showError(qsTr("Not enough battery to capture images."))
+ } else if (!fileSystem.available) {
+ showError(qsTr("Camera cannot capture images in mass storage mode."))
+ } else if (!checkDiskSpace()) {
+ showError(qsTr("Not enough space to capture images."))
+ } else if (!mountProtector.lock()) {
+ showError(qsTr("Failed to lock images directory."))
+ } else {
+ metaData.setMetaData()
+
+ var fileName = fileNaming.imageFileName()
+ if (!imageMode.capture(fileName)) {
+ showError(qsTr("Failed to capture image. Please restart the camera."))
+ mountProtector.unlock()
+ } else {
+ trackerStore.storeImage(fileName)
+ }
+ }
+ }
+
+}
+++ /dev/null
-// -*- qml -*-
-
-/*!
- * This file is part of CameraPlus.
- *
- * 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-import QtQuick 1.1
-import com.nokia.meego 1.1
-import QtCamera 1.0
-import CameraPlus 1.0
-import "data.js" as Data
-
-CameraPage {
- id: page
-
- policyMode: CameraResources.Image
- controlsVisible: imageMode.canCapture && !cameraMode.busy && dimmer.opacity == 0.0 && !previewAnimationRunning && cam.running
-
- orientationLock: PageOrientation.LockLandscape
-
- property Item settingsDialog: null
-
- function cameraError() {
- mountProtector.unlock();
- }
-
- function captureImage() {
- if (!imageMode.canCapture) {
- showError(qsTr("Camera is already capturing an image."));
- return;
- }
-
- if (!checkBattery()) {
- showError(qsTr("Not enough battery to capture images."));
- return;
- }
-
- if (!fileSystem.available) {
- showError(qsTr("Camera cannot capture images in mass storage mode."));
- return;
- }
-
- if (!checkDiskSpace()) {
- showError(qsTr("Not enough space to capture images."));
- return;
- }
-
- if (!mountProtector.lock()) {
- showError(qsTr("Failed to lock images directory."));
- return;
- }
-
- metaData.setMetaData();
-
- var fileName = fileNaming.imageFileName();
- if (!imageMode.capture(fileName)) {
- showError(qsTr("Failed to capture image. Please restart the camera."));
- return;
- }
-
- trackerStore.storeImage(fileName);
- }
-
- CaptureButton {
- id: capture
- anchors.right: parent.right
- anchors.rightMargin: 20
- anchors.verticalCenter: parent.verticalCenter
- iconSource: "image://theme/icon-m-camera-shutter"
- width: 75
- height: 75
- opacity: 0.5
- onClicked: captureImage();
- visible: controlsVisible && (!settings.zoomAsShutter && keys.active)
-
- onExited: {
- if (mouseX <= 0 || mouseY <= 0 || mouseX > width || mouseY > height) {
- // Release outside the button:
- cam.autoFocus.stopAutoFocus();
- }
- }
- }
-
- ZoomCaptureButton {
- id: zoomCapture
- page: page
- onReleased: page.captureImage();
- }
-
- ZoomCaptureCancel {
- anchors.fill: parent
- page: page
- zoomCapture: zoomCapture
- onCanceled: {
- if (!autoFocusTimer.running) {
- cam.autoFocus.stopAutoFocus();
- }
- }
- }
-
- Timer {
- id: autoFocusTimer
- interval: 200
- running: capture.pressed || zoomCapture.zoomPressed
- repeat: false
- onTriggered: {
- if (cam.autoFocus.cafStatus != AutoFocus.Success) {
- cam.autoFocus.startAutoFocus();
- }
- }
- }
-
- ImageMode {
- id: imageMode
- camera: cam
- onPreviewAvailable: {
- page.setPreview(preview);
- cam.autoFocus.stopAutoFocus();
- }
-
- onSaved: mountProtector.unlock();
- }
-
- Rectangle {
- id: indicators
- anchors.top: parent.top
- anchors.topMargin: 20
- anchors.left: parent.left
- anchors.leftMargin: 20
- width: 48
- height: col.height
- color: "black"
- border.color: "gray"
- radius: 20
- opacity: 0.5
- visible: controlsVisible
-
- Column {
- id: col
- width: parent.width
- spacing: 5
-
- Indicator {
- id: resolutionIndicator
- source: "image://theme/" + Data.imageIcon(settings.imageAspectRatio, settings.imageResolution);
- }
-
- Indicator {
- id: wbIndicator
- source: visible ? "image://theme/" + Data.wbIcon(settings.imageWhiteBalance) + "-screen" : ""
- visible: settings.imageWhiteBalance != WhiteBalance.Auto
- }
-
- Indicator {
- id: cfIndicator
- source: "image://theme/" + Data.cfIcon(settings.imageColorFilter) + "-screen"
- visible: settings.imageColorFilter != ColorTone.Normal
- }
-
- Indicator {
- id: isoIndicator
- visible: settings.imageIso != 0
- source: "image://theme/" + Data.isoIcon(settings.imageIso);
- }
-
- Indicator {
- id: gpsIndicator
- visible: settings.useGps
- source: "image://theme/icon-m-camera-location"
-
- PropertyAnimation on opacity {
- easing.type: Easing.OutSine
- loops: Animation.Infinite
- from: 0.2
- to: 1.0
- duration: 1000
- running: settings.useGps && !positionSource.position.longitudeValid
- alwaysRunToEnd: true
- }
- }
-
- Indicator {
- id: faceDetectionIndicator
- visible: settings.faceDetectionEnabled
- source: "image://theme/icon-m-camera-face-detection-screen"
- }
-
- }
- }
-
- Button {
- id: cameraRoll
- anchors.top: parent.top
- anchors.right: parent.right
- anchors.topMargin: 20
- anchors.rightMargin: 20
- width: 56
- height: 56
-
- opacity: 0.5
- iconSource: "image://theme/icon-m-camera-roll"
- onClicked: openFile("PostCapturePage.qml");
- visible: controlsVisible
- }
-
- CameraToolBar {
- id: toolBar
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 20
- anchors.left: parent.left
- anchors.leftMargin: 20
- opacity: 0.5
- targetWidth: parent.width - (anchors.leftMargin * 2) - (66 * 1.5)
- visible: controlsVisible
- expanded: settings.showToolBar
- onExpandedChanged: settings.showToolBar = expanded;
-
- items: [
- FlashButton {
- onClicked: toolBar.push(items);
- },
- ImageSceneButton {
- onClicked: toolBar.push(items);
- },
- ImageEvCompButton {
- onClicked: toolBar.push(items);
- },
- ImageWhiteBalanceButton {
- onClicked: toolBar.push(items);
- },
- ImageColorFilterButton {
- onClicked: toolBar.push(items);
- },
- ImageIsoButton {
- onClicked: toolBar.push(items);
- },
- ToolIcon {
- iconSource: "image://theme/icon-m-toolbar-view-menu-white"
- onClicked: openSettings();
- }
- ]
- }
-
- function openSettings() {
- var roiEnabled = cam.roi.enabled;
- cam.roi.enabled = false;
-
- if (!settingsDialog) {
- settingsDialog = imageSettingsDialog.createObject(page);
- }
-
- settingsDialog.open();
-
- cam.roi.enabled = roiEnabled;
- }
-
- Component {
- id: imageSettingsDialog
-
- ImageSettingsDialog { }
- }
-}
import com.nokia.meego 1.1
Column {
- spacing: 10
+ spacing: 10
- SectionHeader {
- text: qsTr("Aspect ratio");
- }
+ SectionHeader {
+ text: qsTr("Aspect ratio")
+ }
- ButtonRow {
- id: aspectRatioRow
- width: parent.width
- enabled: cam.idle
- exclusive: false
+ ButtonRow {
+ id: aspectRatioRow
+ width: parent.width
+ enabled: cam.idle
+ exclusive: false
- Repeater {
- model: imageSettings.aspectRatios
- delegate: Button {
- text: qsTr(modelData);
- checked: settings.imageAspectRatio == modelData;
- onClicked: settings.imageAspectRatio = modelData;
- }
- }
+ Repeater {
+ model: imageSettings.aspectRatios
+ delegate: Button {
+ text: qsTr(modelData)
+ checked: settings.imageAspectRatio == modelData
+ onClicked: settings.imageAspectRatio = modelData
+ }
}
+ }
- SectionHeader {
- text: qsTr("Resolution");
- }
+ SectionHeader {
+ text: qsTr("Resolution")
+ }
- ButtonRow {
- id: resolutionsRow
- width: parent.width
- enabled: cam.idle
- exclusive: false
+ ButtonRow {
+ id: resolutionsRow
+ width: parent.width
+ enabled: cam.idle
+ exclusive: false
- Binding {
- target: imageSettings.resolutions
- property: "aspectRatio"
- value: settings.imageAspectRatio
- }
+ Binding {
+ target: imageSettings.resolutions
+ property: "aspectRatio"
+ value: settings.imageAspectRatio
+ }
- Repeater {
- id: resolutions
- model: imageSettings.resolutions.aspectRatio == settings.imageAspectRatio ? imageSettings.resolutions : undefined
+ Repeater {
+ id: resolutions
+ model: imageSettings.resolutions.aspectRatio == settings.imageAspectRatio ?
+ imageSettings.resolutions : undefined
- delegate: Button {
- font.capitalization: Font.Capitalize
- text: qsTr("%1 %2 Mpx").arg(resolutionName).arg(megaPixels);
- checked: settings.imageResolution == resolutionName
- onClicked: settings.imageResolution = resolutionName;
- }
- }
+ delegate: Button {
+ font.capitalization: Font.Capitalize
+ text: qsTr("%1 %2 Mpx").arg(resolutionName).arg(megaPixels)
+ checked: settings.imageResolution == resolutionName
+ onClicked: settings.imageResolution = resolutionName
+ }
}
+ }
}
--- /dev/null
+// -*- qml -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+import QtQuick 1.1
+import com.nokia.meego 1.1
+import QtCamera 1.0
+
+Flickable {
+ contentHeight: col.height
+ anchors.fill: parent
+ anchors.margins: 10
+
+ Column {
+ id: col
+ width: parent.width
+ spacing: 10
+
+ Label {
+ font.pixelSize: 36
+ text: qsTr("Image settings")
+ }
+
+ ImageResolutionSettings {
+ width: parent.width
+ }
+
+ TextSwitch {
+ text: qsTr("Enable face detection")
+ // We have to do it that way because QML complains about a binding
+ // loop for checked if we bind the checked property to the settings value.
+ Component.onCompleted: checked = settings.faceDetectionEnabled
+ onCheckedChanged: settings.faceDetectionEnabled = checked
+ }
+
+ CameraSettings {
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+}
+++ /dev/null
-// -*- qml -*-
-
-/*!
- * This file is part of CameraPlus.
- *
- * 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-import QtQuick 1.1
-import com.nokia.meego 1.1
-import QtCamera 1.0
-
-Dialog {
- id: dialog
-
- content: item
-
- Connections {
- target: Qt.application
- onActiveChanged: {
- if (!Qt.application.active) {
- dialog.close();
- }
- }
- }
-
- onStatusChanged: {
- if (status == DialogStatus.Open) {
- cam.renderingEnabled = false;
- }
- else if (status == DialogStatus.Closing) {
- cam.renderingEnabled = true;
- }
- }
-
- Item {
- id: item
- width: parent.width
- height: root.height
-
- Flickable {
- id: flickable
- anchors.fill: parent
- anchors.margins: 10
- contentHeight: col.height
-
- Column {
- id: col
-
- width: parent.width
- spacing: 10
-
- Label {
- font.pixelSize: 36
- text: qsTr("Image settings");
- }
-
- ImageResolutionSettings {
- width: parent.width
- }
-
- TextSwitch {
- text: qsTr("Enable face detection");
- // We have to do it that way because QML complains about a binding
- // loop for checked if we bind the checked property to the settings value.
- Component.onCompleted: checked = settings.faceDetectionEnabled;
- onCheckedChanged: settings.faceDetectionEnabled = checked;
- }
-
- CameraSettings {
- anchors.horizontalCenter: parent.horizontalCenter
- }
- }
- }
- }
-}
import QtQuick 1.1
import QtCamera 1.0
-import com.nokia.meego 1.0
-Item {
- width: selector.width * selector.scale
- height: selector.height * selector.scale
+CaptureButton {
+ width: 55
+ height: 55
+ opacity: 0.5
- Switch {
- id: selector
- scale: 1.5
- anchors.centerIn: parent
- checked: settings.mode == Camera.ImageMode
-
- onCheckedChanged: {
- if (checked) {
- settings.mode = Camera.ImageMode;
- }
- else {
- settings.mode = Camera.VideoMode;
- }
- }
-
- platformStyle: SwitchStyle {
- thumbPressed: settings.mode == Camera.VideoMode ? "image://theme/icon-m-camera-video" : "image://theme/icon-m-viewfinder-camera"
- switchOn: ""
- switchOff: ""
- thumb: settings.mode == Camera.VideoMode ? "image://theme/icon-m-viewfinder-camera" : "image://theme/icon-m-camera-video"
- }
+ iconSource: settings.mode == Camera.VideoMode ?
+ "image://theme/icon-m-viewfinder-camera" :
+ "image://theme/icon-m-camera-video"
+ onClicked: {
+ if (settings.mode == Camera.VideoMode) {
+ settings.mode = Camera.ImageMode
+ } else {
+ settings.mode = Camera.VideoMode
}
+ }
}
import CameraPlus 1.0
Item {
- id: handler
+ id: handler
- property bool showStandBy: state != "on"
+ property bool showStandBy: state != "on"
- property alias acquired: policy.acquired
- property alias hijacked: policy.hijacked
- property alias scaleAcquired: policy.scaleAcquired
+ property alias acquired: policy.acquired
+ property alias hijacked: policy.hijacked
+ property alias scaleAcquired: policy.scaleAcquired
- property Camera camera: null
- property Item currentPage: pageStack.currentPage
- property bool error: false
+ property Camera camera: null
+ property Item currentItem
+ property bool error: false
- onCurrentPageChanged: {
- if (state == "on" || state == "policyLost") {
- startCamera();
- }
+ onCurrentItemChanged: {
+ if (state == "on" || state == "policyLost") {
+ startCamera()
}
-
- CameraResources {
- id: policy
+ }
+
+ Connections {
+ target: currentItem
+ onPolicyModeChanged: {
+ if (state == "on" || state == "policyLost") {
+ startCamera()
+ }
}
-
- function startCamera() {
- if (error) {
- return;
- }
-
- if (!policy.acquire(currentPage.policyMode)) {
- console.log("Failed to acquire policy resources");
- return;
- }
-
- if (!camera.start()) {
- showError(qsTr("Failed to start camera. Please restart the application."));
- }
+ }
+
+ CameraResources {
+ id: policy
+ }
+
+ function startCamera() {
+ if (error) {
+ return
+ } else if (!policy.acquire(currentItem.policyMode)) {
+ console.log("Failed to acquire policy resources")
+ return
+ } else if (!camera.start()) {
+ showError(qsTr("Failed to start camera. Please restart the application."))
}
+ }
- function stopCamera() {
- if (camera.stop(false)) {
- policy.acquire(CameraResources.None);
- error = false;
- }
+ function stopCamera() {
+ if (camera.stop(false)) {
+ policy.acquire(CameraResources.None)
+ error = false
}
+ }
- function forceStopCamera() {
- // We don't release resources here so we can get them back
- // when they become available
- pageStack.currentPage.policyLost();
- camera.stop(true);
- error = false;
- }
+ function forceStopCamera() {
+ // We don't release resources here so we can get them back
+ // when they become available
+ currentItem.policyLost()
+ camera.stop(true)
+ error = false
+ }
- state: "off"
+ state: "off"
-// onStateChanged: console.log("New state " + handler.state);
+// onStateChanged: console.log("New state " + handler.state);
- states: [
+ states: [
State {
- name: "on"
- when: Qt.application.active && currentPage && currentPage.policyMode != CameraResources.None && !policy.hijacked
+ name: "on"
+ when: Qt.application.active && currentItem && currentItem.policyMode != CameraResources.None && !policy.hijacked
},
State {
- name: "off"
- when: (!Qt.application.active && camera.idle) || (currentPage && currentPage.policyMode == CameraResources.None && camera.idle)
+ name: "off"
+ when: (!Qt.application.active && camera.idle) || (currentItem && currentItem.policyMode == CameraResources.None && camera.idle)
},
State {
- name: "policyLost"
- when: policy.hijacked
+ name: "policyLost"
+ when: policy.hijacked
},
State {
- name: "error"
+ name: "error"
}
- ]
+ ]
- transitions: [
+ transitions: [
Transition {
- to: "off"
- ScriptAction {
- script: stopCamera();
- }
+ to: "off"
+ ScriptAction {
+ script: stopCamera()
+ }
},
Transition {
- from: "off"
- to: "on"
- ScriptAction {
- script: handler.startCamera();
- }
+ from: "off"
+ to: "on"
+ ScriptAction {
+ script: handler.startCamera()
+ }
},
-
Transition {
- from: "on"
- to: "policyLost"
- ScriptAction {
- script: forceStopCamera();
- }
+ from: "on"
+ to: "policyLost"
+ ScriptAction {
+ script: forceStopCamera()
+ }
},
-
Transition {
- from: "policyLost"
- to: "off"
- ScriptAction {
- script: stopCamera();
- }
+ from: "policyLost"
+ to: "off"
+ ScriptAction {
+ script: stopCamera()
+ }
},
Transition {
- from: "policyLost"
- to: "on"
- ScriptAction {
- script: startCamera();
- }
+ from: "policyLost"
+ to: "on"
+ ScriptAction {
+ script: startCamera()
+ }
}
- ]
+ ]
}
import CameraPlus 1.0
Item {
- id: postCaptureItem
- property bool isVideo: itemData.type.search("nmm#Video") > 0
- property alias error: image.error
- property variant itemData: item
- property bool isCurrentItem: PathView.isCurrentItem
- signal clicked
+ id: postCaptureItem
+ property bool isVideo: itemData.type.search("nmm#Video") > 0
+ property alias error: image.error
+ property variant itemData: item
+ property bool playing: loader.source != ""
+ signal clicked
- onIsCurrentItemChanged: {
- if (isCurrentItem) {
- page.currentItem = postCaptureItem;
- }
- }
-
- function startPlayback() {
- openFileNow("VideoPlayerPage.qml");
- pageStack.currentPage.source = itemData.url;
- pageStack.currentPage.play();
- }
+ function startPlayback() {
+ loader.source = Qt.resolvedUrl("VideoPlayerPage.qml")
+ loader.item.source = itemData.url
+ loader.item.play()
+ }
- Label {
- anchors.fill: parent
- visible: image.error && page.status == PageStatus.Active
- text: qsTr("Failed to load preview");
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignHCenter
- font.pixelSize: 32
- }
+ Loader {
+ id: loader
+ anchors.fill: parent
+ }
- QuillItem {
- id: image
- width: parent.width - 10
- height: parent.height
- anchors.centerIn: parent
+ Connections {
+ target: loader.item
+ onFinished: loader.source = ""
+ }
- visible: page.status == PageStatus.Activating || page.status == PageStatus.Active && !error
+ QuillItem {
+ id: image
+ width: parent.width - 10
+ height: parent.height
+ anchors.centerIn: parent
+ Component.onCompleted: initialize(itemData.url, itemData.mimetype)
+ visible: loader.source == ""
- Component.onCompleted: initialize(itemData.url, itemData.mimetype);
+ Label {
+ anchors.fill: parent
+ visible: image.error
+ text: qsTr("Failed to load preview")
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: 32
+ }
- MouseArea {
- id: mouse
- anchors.fill: parent
- enabled: true
- onClicked: postCaptureItem.clicked();
- }
+ MouseArea {
+ id: mouse
+ anchors.fill: parent
+ enabled: true
+ onClicked: postCaptureItem.clicked()
+ }
- ToolIcon {
- id: playIcon
- anchors.centerIn: parent
- iconSource: "image://theme/icon-s-music-video-play"
- visible: isVideo
- onClicked: startPlayback();
- }
+ ToolIcon {
+ // TODO: this is overlapping with error.
+ id: playIcon
+ anchors.centerIn: parent
+ iconSource: "image://theme/icon-s-music-video-play"
+ visible: isVideo
+ onClicked: startPlayback()
}
+ }
}
Component.onCompleted: postCaptureModel.reload();
- function launchGallery() {
- if (!gallery.launch()) {
- showError(qsTr("Failed to launch gallery"));
- }
- }
-
- function showInGallery() {
- if (!available) {
- return;
- }
-
- if (!gallery.show(currentItem.itemUrl)) {
- showError(qsTr("Failed to launch gallery"));
- }
- }
-
- Menu {
- id: menu
- onStatusChanged: page.restartTimer();
-
- MenuLayout {
- MenuItem {text: qsTr("Captures in gallery"); onClicked: launchGallery(); }
- MenuItem {text: qsTr("View in gallery"); enabled: available; onClicked: showInGallery(); }
- }
- }
-
- function deleteCurrentItem() {
- if (!available) {
- return;
- }
-
- deleteDialog.message = currentItem.itemData.fileName;
- deleteDialog.open();
- }
-
- QueryDialog {
- id: deleteDialog
- titleText: qsTr("Delete item?");
- acceptButtonText: qsTr("Yes");
- rejectButtonText: qsTr("No");
-
- onStatusChanged: page.restartTimer();
-
- onAccepted: {
- if (!remove.remove(currentItem.itemData.url)) {
- showError(qsTr("Failed to delete item"));
- }
- else {
- postCaptureModel.remove(currentItem.itemData);
- }
- }
-
- DeleteHelper {
- id: remove
- }
- }
-
- function shareCurrentItem() {
- if (!available) {
- return;
- }
-
- if (!share.share(currentItem.itemData.url)) {
- showError(qsTr("Failed to launch share service"));
- }
- }
-
- function addOrRemoveFavorite() {
- if (!available) {
- return;
- }
-
- if (currentItem.itemData.favorite) {
- if (!trackerStore.removeFromFavorites(currentItem.itemData.url)) {
- showError(qsTr("Failed to remove favorite"));
- }
- else {
- currentItem.itemData.favorite = false;
- }
- }
- else {
- if (!trackerStore.addToFavorites(currentItem.itemData.url)) {
- showError(qsTr("Failed to add favorite"));
- }
- else {
- currentItem.itemData.favorite = true;
- }
- }
- }
-
- ShareHelper {
- id: share
- settings: platformSettings
- }
-
- GalleryHelper {
- id: gallery
- settings: platformSettings
- }
-
Rectangle {
color: "black"
anchors.fill: parent
onClicked: hideTimer.running = !hideTimer.running;
}
}
-
- function restartTimer() {
- hideTimer.running = true;
- }
-
- Timer {
- id: hideTimer
- running: false
- interval: 3000
- }
-
- CameraToolBar {
- id: toolBar
- expanded: true
- manualBack: true
- anchors.bottom: parent.bottom
- anchors.bottomMargin: show ? 20 : -1 * (height + 20)
- anchors.left: parent.left
- anchors.leftMargin: 20
- opacity: 0.8
-
- property bool show: deleteDialog.status == DialogStatus.Open || deleteDialog.status == DialogStatus.Opening || hideTimer.running || menu.status == DialogStatus.Open || menu.status == DialogStatus.Opening || (currentItem && currentItem.error)
-
- onClicked: pageStack.pop();
-
- Behavior on anchors.bottomMargin {
- PropertyAnimation { duration: 200; }
- }
-
- items: [
- ToolIcon { iconId: !available ? "icon-m-toolbar-favorite-mark-dimmed-white" : currentItem.itemData.favorite ? "icon-m-toolbar-favorite-mark-white" : "icon-m-toolbar-favorite-unmark-white"; onClicked: { addOrRemoveFavorite(); page.restartTimer(); } },
- ToolIcon { iconId: available ? "icon-m-toolbar-share-white" : "icon-m-toolbar-share-dimmed-white"; onClicked: { shareCurrentItem(); page.restartTimer(); } },
- ToolIcon { iconId: available ? "icon-m-toolbar-delete-white" : "icon-m-toolbar-delete-dimmed-white"; onClicked: { deleteCurrentItem(); page.restartTimer(); } },
- ToolIcon { iconId: "icon-m-toolbar-view-menu-white"; onClicked: { menu.open(); page.restartTimer(); } }
- ]
- }
-
- Rectangle {
- opacity: toolBar.opacity
- anchors.top: parent.top
- anchors.topMargin: toolBar.show ? 20 : -1 * (height + 20)
- anchors.left: parent.left
- anchors.leftMargin: 20
- anchors.right: parent.right
- anchors.rightMargin: 20
- visible: toolBar.visible
- height: screen.isPortrait ? toolBar.height * 2 : toolBar.height
- color: toolBar.color
- border.color: toolBar.border.color
- radius: toolBar.radius
-
- Behavior on anchors.topMargin {
- PropertyAnimation { duration: 200; }
- }
-
- Flow {
- width: parent.width - 40
- x: 20
- height: parent.height
-
- Label {
- text: currentItem ? currentItem.itemData.title : ""
- width: parent.width / 2
- height: parent.height
- font.bold: true
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignLeft
- }
-
- Label {
- text: currentItem ? currentItem.itemData.created : ""
- width: parent.width / 2
- height: parent.height
- font.bold: true
- verticalAlignment: Text.AlignVCenter
- horizontalAlignment: Text.AlignRight
- }
- }
- }
}
--- /dev/null
+// -*- qml -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+import QtQuick 1.1
+import CameraPlus 1.0
+import com.nokia.meego 1.1
+
+Item {
+ property bool pressed: view.currentItem ? view.currentItem.playing : false
+ property int policyMode: CameraResources.None
+ property bool available: view.currentItem ? view.currentItem.itemData.available : false
+
+ Component.onCompleted: postCaptureModel.reload()
+
+ ShareHelper {
+ id: share
+ settings: platformSettings
+ }
+
+ GalleryHelper {
+ id: gallery
+ settings: platformSettings
+ }
+
+ ListView {
+ id: view
+ anchors.fill: parent
+ snapMode: ListView.SnapOneItem
+ cacheBuffer: height * 3
+ model: postCaptureModel
+ highlightRangeMode: ListView.StrictlyEnforceRange
+
+ delegate: PostCaptureItem {
+ width: view.width
+ height: view.height
+ onClicked: hideTimer.running = !hideTimer.running
+ }
+
+ onFlickingChanged: {
+ if (flicking && hideTimer.running) {
+ restartTimer()
+ }
+ }
+ }
+
+ PostCaptureModel {
+ // TODO: this should not be active all the time
+ id: postCaptureModel
+ manufacturer: deviceInfo.manufacturer
+ model: deviceInfo.model
+ onError: {
+ console.log("Error populating model " + msg)
+ showError(qsTr("Failed to load captures"))
+ }
+ }
+
+ Timer {
+ id: hideTimer
+ running: false
+ interval: 3000
+ }
+
+ CameraToolBar {
+ id: toolBar
+ expanded: true
+ manualBack: true
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: show ? 20 : -1 * (height + 20)
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ opacity: 0.8
+// TODO: hide back button
+ property bool show: deleteDialog.status == DialogStatus.Open ||
+ deleteDialog.status == DialogStatus.Opening ||
+ hideTimer.running || menu.status == DialogStatus.Open ||
+ menu.status == DialogStatus.Opening ||
+ (view.currentItem && view.currentItem.error) && !view.currentItem.playing
+
+// TODO:
+// onClicked: pageStack.pop()
+
+ Behavior on anchors.bottomMargin {
+ PropertyAnimation { duration: 200; }
+ }
+
+ items: [
+ ToolIcon {
+ iconId: !available ? "icon-m-toolbar-favorite-mark-dimmed-white" : view.currentItem.itemData.favorite ? "icon-m-toolbar-favorite-mark-white" : "icon-m-toolbar-favorite-unmark-white"
+ onClicked: {
+ addOrRemoveFavorite()
+ restartTimer()
+ }
+ },
+ ToolIcon {
+ iconId: available ? "icon-m-toolbar-share-white" : "icon-m-toolbar-share-dimmed-white"
+ onClicked: {
+ shareCurrentItem()
+ restartTimer()
+ }
+ },
+ ToolIcon {
+ iconId: available ? "icon-m-toolbar-delete-white" : "icon-m-toolbar-delete-dimmed-white"
+ onClicked: {
+ deleteCurrentItem()
+ restartTimer()
+ }
+ },
+ ToolIcon {
+ iconId: "icon-m-toolbar-view-menu-white"
+ onClicked: {
+ menu.open()
+ restartTimer()
+ }
+ }
+ ]
+ }
+
+ QueryDialog {
+ id: deleteDialog
+ titleText: qsTr("Delete item?");
+ acceptButtonText: qsTr("Yes");
+ rejectButtonText: qsTr("No");
+
+ onStatusChanged: restartTimer()
+
+ onAccepted: {
+ if (!remove.remove(view.currentItem.itemData.url)) {
+ showError(qsTr("Failed to delete item"))
+ } else {
+ postCaptureModel.remove(view.currentItem.itemData);
+ }
+ }
+
+ DeleteHelper {
+ id: remove
+ }
+ }
+
+ Menu {
+ id: menu
+ onStatusChanged: restartTimer()
+
+ MenuLayout {
+ MenuItem {
+ text: qsTr("Captures in gallery")
+ onClicked: launchGallery()
+ }
+
+ MenuItem {
+ text: qsTr("View in gallery")
+ enabled: available
+ onClicked: showInGallery()
+ }
+ }
+ }
+
+ Rectangle {
+ opacity: toolBar.opacity
+ anchors.top: parent.top
+ anchors.topMargin: toolBar.show ? 20 : -1 * (height + 20)
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ anchors.right: parent.right
+ anchors.rightMargin: 20
+ visible: toolBar.visible
+ height: screen.isPortrait ? toolBar.height * 2 : toolBar.height
+ color: toolBar.color
+ border.color: toolBar.border.color
+ radius: toolBar.radius
+
+ Behavior on anchors.topMargin {
+ PropertyAnimation { duration: 200; }
+ }
+
+ Flow {
+ width: parent.width - 40
+ x: 20
+ height: parent.height
+
+ Label {
+ text: view.currentItem ? view.currentItem.itemData.title : ""
+ width: parent.width / 2
+ height: parent.height
+ font.bold: true
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignLeft
+ }
+
+ Label {
+ text: view.currentItem ? view.currentItem.itemData.created : ""
+ width: parent.width / 2
+ height: parent.height
+ font.bold: true
+ verticalAlignment: Text.AlignVCenter
+ horizontalAlignment: Text.AlignRight
+ }
+ }
+ }
+
+ function launchGallery() {
+ if (!gallery.launch()) {
+ showError(qsTr("Failed to launch gallery"))
+ }
+ }
+
+ function showInGallery() {
+ if (!available) {
+ return
+ }
+
+ if (!gallery.show(view.currentItem.itemUrl)) {
+ showError(qsTr("Failed to launch gallery"))
+ }
+ }
+
+ function deleteCurrentItem() {
+ if (!available) {
+ return
+ }
+
+ deleteDialog.message = view.currentItem.itemData.fileName
+ deleteDialog.open()
+ }
+
+ function shareCurrentItem() {
+ if (!available) {
+ return
+ }
+
+ if (!share.share(view.currentItem.itemData.url)) {
+ showError(qsTr("Failed to launch share service"))
+ }
+ }
+
+ function addOrRemoveFavorite() {
+ if (!available) {
+ return
+ }
+
+ if (view.currentItem.itemData.favorite) {
+ if (!trackerStore.removeFromFavorites(view.currentItem.itemData.url)) {
+ showError(qsTr("Failed to remove favorite"))
+ } else {
+ view.currentItem.itemData.favorite = false
+ }
+ } else {
+ if (!trackerStore.addToFavorites(view.currentItem.itemData.url)) {
+ showError(qsTr("Failed to add favorite"))
+ } else {
+ view.currentItem.itemData.favorite = true
+ }
+ }
+ }
+
+ function restartTimer() {
+ hideTimer.restart()
+ }
+}
import QtCamera 1.0
Image {
- id: image
- anchors.fill: parent
- property alias animationRunning: animation.running
- opacity: visible ? 1 : 0
- z: 1
+ id: image
+ anchors.fill: parent
+ property alias animationRunning: animation.running
- visible: opacity != 0
+ visible: opacity != 0
- cache: false
- fillMode: Image.PreserveAspectFit
+ cache: false
+ fillMode: Image.PreserveAspectFit
- MouseArea {
- anchors.fill: parent
- enabled: parent.visible
- }
+ MouseArea {
+ anchors.fill: parent
+ enabled: parent.visible
+ }
- SequentialAnimation {
- id: animation
- PauseAnimation { duration: 500; alwaysRunToEnd: true }
- NumberAnimation { target: preview; property: "opacity"; from: 1; to: 0; duration: 250; alwaysRunToEnd: true }
+ SequentialAnimation {
+ id: animation
+ PauseAnimation {
+ duration: 500
+ alwaysRunToEnd: true
}
- function setPreview(preview) {
- image.source = preview;
- image.opacity = 1;
- animation.start();
+ NumberAnimation {
+ target: preview
+ property: "opacity"
+ from: 1
+ to: 0
+ duration: 250
+ alwaysRunToEnd: true
}
+ }
+
+ function setPreview(preview) {
+ image.source = preview
+ image.opacity = 1
+ animation.start()
+ }
}
--- /dev/null
+// -*- qml -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+import QtQuick 1.1
+import com.nokia.meego 1.1
+
+Rectangle {
+ property int duration
+
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ anchors.rightMargin: 20
+ anchors.bottomMargin: 20
+
+ color: "black"
+ opacity: 0.5
+ width: 100
+ height: 30
+
+ Image {
+ id: recordingIcon
+ source: "image://theme/icon-m-camera-ongoing-recording"
+ width: 20
+ height: 20
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ sourceSize.width: 20
+ sourceSize.height: 20
+ }
+
+ Label {
+ function formatDuration(dur) {
+ var secs = parseInt(recordingDuration.duration)
+ var minutes = Math.floor(secs / 60)
+ var seconds = secs - (minutes * 60)
+
+ var date = new Date()
+ date.setSeconds(seconds)
+ date.setMinutes(minutes)
+ return Qt.formatTime(date, "mm:ss")
+ }
+
+ text: formatDuration(parent.duration)
+ anchors.left: recordingIcon.right
+ anchors.leftMargin: 5
+ }
+}
+++ /dev/null
-// -*- qml -*-
-
-/*!
- * This file is part of CameraPlus.
- *
- * 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-import QtQuick 1.1
-import com.nokia.meego 1.1
-import QtCamera 1.0
-import CameraPlus 1.0
-import "data.js" as Data
-
-// TODO: optional resources?
-
-CameraPage {
- id: page
- activationData: ControlsActivationData {modeSelectorVisible: false}
- property bool error: false
-
- policyMode: CameraResources.Recording
-
- controlsVisible: cam.running && videoMode.recording && !error
-
- orientationLock: PageOrientation.LockLandscape
-
- function policyLost() {
- page.stopRecording();
- }
-
- function cameraError() {
- error = true;
- page.stopRecording();
- }
-
- onStatusChanged: {
- if (page.status == PageStatus.Active) {
- startRecording();
- }
- }
-
- function startRecording() {
- if (!pipelineManager.acquired || pipelineManager.hijacked) {
- showError(qsTr("Failed to acquire needed resources."));
- pageStack.pop(undefined, true);
- return;
- }
-
- metaData.setMetaData();
-
- if (!mountProtector.lock()) {
- showError(qsTr("Failed to lock images directory."));
- pageStack.pop(undefined, true);
- return;
- }
-
- var file = fileNaming.videoFileName();
- var tmpFile = fileNaming.temporaryVideoFileName();
-
- if (!videoMode.startRecording(file, tmpFile)) {
- showError(qsTr("Failed to record video. Please restart the camera."));
- pageStack.pop(undefined, true);
- mountProtector.unlock();
- }
-
- trackerStore.storeVideo(file);
- }
-
- function stopRecording() {
- videoMode.stopRecording(true);
- mountProtector.unlock();
- // Something is fishy here but if there is an error
- // and we use immediate mode then the page never gets destroyed.
- pageStack.pop(undefined, error ? false : true);
- }
-
- DisplayState {
- inhibitDim: true
- }
-
- onBatteryLow: {
- if (!checkBattery()) {
- page.stopRecording();
- showError(qsTr("Not enough battery to record video."));
- }
- }
-
- ZoomCaptureButton {
- id: zoomCapture
- page: page
- onReleased: page.stopRecording();
- }
-
- ZoomCaptureCancel {
- anchors.fill: parent
- page: page
- zoomCapture: zoomCapture
- }
-
- CaptureButton {
- id: recording
- anchors.right: parent.right
- anchors.rightMargin: 20
- anchors.verticalCenter: parent.verticalCenter
- iconSource: "image://theme/icon-m-camera-video-record"
- width: 75
- height: 75
- opacity: 0.5
-
- onClicked: page.stopRecording();
- visible: controlsVisible && (!settings.zoomAsShutter && keys.active)
- }
-
- Connections {
- target: Qt.application
- onActiveChanged: {
- if (!Qt.application.active) {
- page.stopRecording();
- }
- }
- }
-
- VideoMode {
- id: videoMode
- camera: cam
- }
-
- Rectangle {
- anchors.top: parent.top
- anchors.topMargin: 20
- anchors.left: parent.left
- anchors.leftMargin: 20
- width: 48
- height: col.height
- color: "black"
- border.color: "gray"
- radius: 20
- opacity: 0.5
- visible: controlsVisible
-
- Column {
- id: col
- width: parent.width
- spacing: 5
-
- Indicator {
- id: resolutionIndicator
- source: "image://theme/" + Data.videoIcon(settings.videoResolution);
- }
-
- Indicator {
- id: wbIndicator
- source: visible ? "image://theme/" + Data.wbIcon(settings.videoWhiteBalance) + "-screen" : ""
- visible: settings.videoWhiteBalance != WhiteBalance.Auto
- }
-
- Indicator {
- id: cfIndicator
- source: "image://theme/" + Data.cfIcon(settings.videoColorFilter) + "-screen"
- visible: settings.videoColorFilter != ColorTone.Normal
- }
-
- Indicator {
- id: gpsIndicator
- visible: settings.useGps
- source: "image://theme/icon-m-camera-location"
-
- PropertyAnimation on opacity {
- easing.type: Easing.OutSine
- loops: Animation.Infinite
- from: 0.2
- to: 1.0
- duration: 1000
- running: settings.useGps && !positionSource.position.longitudeValid
- alwaysRunToEnd: true
- }
- }
- }
- }
-
- Rectangle {
- anchors.bottom: parent.bottom
- anchors.right: parent.right
- anchors.rightMargin: 20
- anchors.bottomMargin: 20
-
- visible: controlsVisible
-
- color: "black"
- opacity: 0.5
- width: 100
- height: 30
-
- Timer {
- id: recordingDuration
-
- property int duration: 0
-
- running: videoMode.recording
- interval: 1000
- repeat: true
-
- onTriggered: {
- duration = duration + 1;
- if (duration == 3600) {
- page.stopRecording();
- showError(qsTr("Maximum recording time reached."));
- }
- else if (!checkDiskSpace()) {
- page.stopRecording();
- showError(qsTr("Not enough space to continue recording."));
- }
- }
- }
-
- Image {
- id: recordingIcon
- source: "image://theme/icon-m-camera-ongoing-recording"
- width: 20
- height: 20
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: 5
- sourceSize.width: 20
- sourceSize.height: 20
- }
-
- Label {
- function formatDuration(dur) {
- var secs = parseInt(recordingDuration.duration);
- var minutes = Math.floor(secs / 60);
- var seconds = secs - (minutes * 60);
-
- var date = new Date();
- date.setSeconds(seconds);
- date.setMinutes(minutes);
- return Qt.formatTime(date, "mm:ss");
- }
-
- id: durationLabel
- text: formatDuration(recordingDuration.duration);
- anchors.left: recordingIcon.right
- anchors.leftMargin: 5
- }
- }
-
- CameraToolBar {
- id: toolBar
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 20
- anchors.left: parent.left
- anchors.leftMargin: 20
- opacity: 0.5
- targetWidth: parent.width - (anchors.leftMargin * 2) - (66 * 1.5)
- visible: controlsVisible
- expanded: settings.showToolBar
- onExpandedChanged: settings.showToolBar = expanded;
-
- items: [
- VideoTorchButton {
- camera: cam
- },
- VideoEvCompButton {
- onClicked: toolBar.push(items);
- },
- VideoWhiteBalanceButton {
- onClicked: toolBar.push(items);
- },
- VideoColorFilterButton {
- onClicked: toolBar.push(items);
- },
- VideoMuteButton {
- },
- ToolIcon {
- iconSource: "image://theme/icon-m-toolbar-view-menu-white"
- onClicked: openFile("VideoSettingsPage.qml");
- }
- ]
- }
-}
import com.nokia.meego 1.1
Row {
- id: root
+ id: root
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.leftMargin: 10
- anchors.rightMargin: 10
- spacing: 10
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.leftMargin: 10
+ anchors.rightMargin: 10
+ spacing: 10
- property alias text: label.text
+ property alias text: label.text
- Label {
- id: label
- verticalAlignment: Text.AlignVCenter
- }
+ Label {
+ id: label
+ verticalAlignment: Text.AlignVCenter
+ }
- Rectangle {
- color: "darkgray"
- height: 2
- width: parent.width - label.width - 20
- anchors.verticalCenter: parent.verticalCenter
- }
+ Rectangle {
+ color: "darkgray"
+ height: 2
+ width: parent.width - label.width - 20
+ anchors.verticalCenter: parent.verticalCenter
+ }
}
*/
import QtQuick 1.1
+import QtCamera 1.0
+import CameraPlus 1.0
-QtObject {
- property bool zoomBarVisible: true
- property bool modeSelectorVisible: true
- property bool standbyVisible: true
+Item {
+ property int policyMode: settings.mode == Camera.VideoMode ? CameraResources.Video
+ : CameraResources.Image
-/*
-// TODO:
- property bool focusReticleVisible: true
- property bool captureButtonVisible: true
- property bool viewfinderEnabled: true
-*/
+ Loader {
+ id: loader
+ anchors.fill: parent
+ source: settings.mode == Camera.VideoMode ? Qt.resolvedUrl("VideoSettings.qml") : Qt.resolvedUrl("ImageSettings.qml")
+ }
}
import com.nokia.meego 1.1
Item {
- property alias text: label.text
- property alias checked: switchComponent.checked
- width: parent.width
- height: switchComponent.height
+ property alias text: label.text
+ property alias checked: switchComponent.checked
+ width: parent.width
+ height: switchComponent.height
- Text {
- property Style platformStyle: LabelStyle {}
+ Text {
+ property Style platformStyle: LabelStyle {}
- id: label
- anchors.left: parent.left
- font.family: platformStyle.fontFamily
- font.pixelSize: platformStyle.fontPixelSize
- color: platformStyle.textColor
- wrapMode: Text.Wrap
- }
+ id: label
+ anchors.left: parent.left
+ font.family: platformStyle.fontFamily
+ font.pixelSize: platformStyle.fontPixelSize
+ color: platformStyle.textColor
+ wrapMode: Text.Wrap
+ }
- Switch {
- id: switchComponent
- anchors.right: parent.right
- }
+ Switch {
+ id: switchComponent
+ anchors.right: parent.right
+ }
}
--- /dev/null
+// -*- qml -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+import QtQuick 1.1
+import com.nokia.meego 1.1
+import QtCamera 1.0
+import CameraPlus 1.0
+import "data.js" as Data
+
+Item {
+ id: overlay
+ property bool recording: false
+
+ property Camera cam
+ property bool animationRunning: false
+ property int policyMode: recording == true ? CameraResources.Recording : CameraResources.Video
+ property bool controlsVisible: !animationRunning && cam.running && dimmer.opacity == 0.0
+ && !cameraMode.busy
+// TODO:
+ property bool pressed: overlay.recording || capture.pressed ||
+ zoomSlider.pressed || modeButton.pressed
+
+ signal previewAvailable(string uri)
+
+ anchors.fill: parent
+
+ VideoMode {
+ id: videoMode
+ camera: cam
+ onPreviewAvailable: overlay.previewAvailable(preview)
+ }
+
+ ZoomSlider {
+ id: zoomSlider
+ camera: cam
+ anchors.top: parent.top
+ anchors.topMargin: 0
+ anchors.horizontalCenter: parent.horizontalCenter
+ visible: controlsVisible
+ }
+
+ ModeButton {
+ id: modeButton
+ anchors.bottom: parent.bottom
+ anchors.right: parent.right
+ anchors.rightMargin: 20
+ anchors.bottomMargin: 20
+ visible: controlsVisible && !overlay.recording
+ }
+
+ ZoomCaptureButton {
+ id: zoomCapture
+ onReleased: overlay.toggleRecording()
+ }
+
+ ZoomCaptureCancel {
+ anchors.fill: parent
+ zoomCapture: zoomCapture
+ }
+
+ CaptureButton {
+ id: capture
+ anchors.right: parent.right
+ anchors.rightMargin: 20
+ anchors.verticalCenter: parent.verticalCenter
+ iconSource: overlay.recording ? "image://theme/icon-m-camera-video-record" : "image://theme/icon-m-camera-video-record"
+ width: 75
+ height: 75
+ opacity: 0.5
+
+ onClicked: overlay.toggleRecording()
+
+ visible: controlsVisible && (!settings.zoomAsShutter && keys.active)
+ }
+
+ CameraToolBar {
+ id: toolBar
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 20
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ opacity: 0.5
+ targetWidth: parent.width - (anchors.leftMargin * 2) - (66 * 1.5)
+ visible: controlsVisible
+ expanded: settings.showToolBar
+ onExpandedChanged: settings.showToolBar = expanded;
+
+ items: [
+ VideoTorchButton {
+ camera: cam
+ },
+ VideoSceneButton {
+// TODO: hide when recording
+ onClicked: toolBar.push(items)
+ },
+ VideoEvCompButton {
+ onClicked: toolBar.push(items)
+ },
+ VideoWhiteBalanceButton {
+ onClicked: toolBar.push(items)
+ },
+ VideoColorFilterButton {
+ onClicked: toolBar.push(items)
+ },
+ VideoMuteButton {
+ }
+ ]
+ }
+
+ Rectangle {
+ anchors.top: parent.top
+ anchors.topMargin: 20
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ width: 48
+ height: col.height
+ color: "black"
+ border.color: "gray"
+ radius: 20
+ opacity: 0.5
+ visible: controlsVisible
+
+ Column {
+ id: col
+ width: parent.width
+ spacing: 5
+
+ Indicator {
+ id: resolutionIndicator
+ source: "image://theme/" + Data.videoIcon(settings.videoResolution)
+ }
+
+ Indicator {
+ id: wbIndicator
+ source: visible ? "image://theme/" + Data.wbIcon(settings.videoWhiteBalance) + "-screen" : ""
+ visible: settings.videoWhiteBalance != WhiteBalance.Auto
+ }
+
+ Indicator {
+ id: cfIndicator
+ source: "image://theme/" + Data.cfIcon(settings.videoColorFilter) + "-screen"
+ visible: settings.videoColorFilter != ColorTone.Normal
+ }
+
+ Indicator {
+ id: gpsIndicator
+ visible: settings.useGps
+ source: "image://theme/icon-m-camera-location"
+
+ PropertyAnimation on opacity {
+ easing.type: Easing.OutSine
+ loops: Animation.Infinite
+ from: 0.2
+ to: 1.0
+ duration: 1000
+ running: settings.useGps && !positionSource.position.longitudeValid
+ alwaysRunToEnd: true
+ }
+ }
+ }
+ }
+
+ DisplayState {
+ inhibitDim: overlay.recording
+ }
+
+ Connections {
+ target: Qt.application
+ onActiveChanged: {
+ if (!Qt.application.active && overlay.recording) {
+ overlay.stopRecording()
+ }
+ }
+ }
+
+ Timer {
+ id: recordingDuration
+ property int duration: 0
+ running: overlay.recording
+ interval: 1000
+ repeat: true
+
+ onTriggered: {
+ duration = duration + 1
+
+ if (duration == 3600) {
+ overlay.stopRecording()
+ showError(qsTr("Maximum recording time reached."))
+ } else if (!checkDiskSpace()) {
+ page.stopRecording()
+ showError(qsTr("Not enough space to continue recording."))
+ }
+
+ }
+ }
+
+ RecordingDurationLabel {
+ visible: overlay.recording
+ duration: recordingDuration.duration
+ }
+
+ function doStartRecording() {
+ if (!overlay.recording) {
+ return
+ }
+
+ if (!pipelineManager.acquired || pipelineManager.hijacked) {
+ showError(qsTr("Failed to acquire needed resources."))
+ overlay.recording = false
+ return
+ }
+
+ metaData.setMetaData()
+
+ if (!mountProtector.lock()) {
+ showError(qsTr("Failed to lock images directory."))
+ overlay.recording = false
+ return
+ }
+
+ var file = fileNaming.videoFileName()
+ var tmpFile = fileNaming.temporaryVideoFileName()
+
+ if (!videoMode.startRecording(file, tmpFile)) {
+ showError(qsTr("Failed to record video. Please restart the camera."))
+ mountProtector.unlock()
+ overlay.recording = false
+ return
+ }
+
+ trackerStore.storeVideo(file);
+ }
+
+ function startRecording() {
+ if (!fileSystem.available) {
+ showError(qsTr("Camera cannot record videos in mass storage mode."))
+ } else if (!checkBattery()) {
+ showError(qsTr("Not enough battery to record video."))
+ } else if (!checkDiskSpace()) {
+ showError(qsTr("Not enough space to record video."))
+ } else {
+ recordingDuration.duration = 0
+ overlay.recording = true
+ doStartRecording()
+ }
+ }
+
+ function stopRecording() {
+ videoMode.stopRecording(true)
+ mountProtector.unlock()
+ overlay.recording = false
+ }
+
+ function toggleRecording() {
+ if (overlay.recording) {
+ overlay.stopRecording()
+ } else {
+ overlay.startRecording()
+ }
+ }
+
+ function cameraError() {
+ overlay.stopRecording()
+ }
+
+ function policyLost() {
+ overlay.stopRecording()
+ }
+
+ function batteryLow() {
+ if (!overlay.recording) {
+ return
+ }
+
+ if (!checkBattery()) {
+ overlay.stopRecording()
+ showError(qsTr("Not enough battery to record video."))
+ }
+ }
+
+}
+++ /dev/null
-// -*- qml -*-
-
-/*!
- * This file is part of CameraPlus.
- *
- * 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-import QtQuick 1.1
-import com.nokia.meego 1.1
-import QtCamera 1.0
-import CameraPlus 1.0
-import "data.js" as Data
-
-CameraPage {
- id: page
-
- policyMode: CameraResources.Video
-
- controlsVisible: cam.running && !videoMode.recording && videoMode.canCapture && !cameraMode.busy && dimmer.opacity == 0.0 && !previewAnimationRunning
- orientationLock: PageOrientation.LockLandscape
-
- property Item settingsDialog: null
-
- function startRecording() {
- if (!fileSystem.available) {
- showError(qsTr("Camera cannot record videos in mass storage mode."));
- return;
- }
-
- if (!checkBattery()) {
- showError(qsTr("Not enough battery to record video."));
- return;
- }
-
- if (!checkDiskSpace()) {
- showError(qsTr("Not enough space to record video."));
- return;
- }
-
- openFileNow("RecordingPage.qml");
- }
-
- ZoomCaptureButton {
- id: zoomCapture
- page: page
- onReleased: page.startRecording();
- }
-
- ZoomCaptureCancel {
- anchors.fill: parent
- page: page
- zoomCapture: zoomCapture
- }
-
- CaptureButton {
- id: recording
- anchors.right: parent.right
- anchors.rightMargin: 20
- anchors.verticalCenter: parent.verticalCenter
- iconSource: "image://theme/icon-m-camera-video-record"
- width: 75
- height: 75
- opacity: 0.5
-
- onClicked: startRecording();
-
- visible: controlsVisible && (!settings.zoomAsShutter && keys.active)
- }
-
- VideoMode {
- id: videoMode
- camera: cam
- onPreviewAvailable: {
- page.setPreview(preview);
- }
- }
-
- Rectangle {
- anchors.top: parent.top
- anchors.topMargin: 20
- anchors.left: parent.left
- anchors.leftMargin: 20
- width: 48
- height: col.height
- color: "black"
- border.color: "gray"
- radius: 20
- opacity: 0.5
- visible: controlsVisible
-
- Column {
- id: col
- width: parent.width
- spacing: 5
-
- Indicator {
- id: resolutionIndicator
- source: "image://theme/" + Data.videoIcon(settings.videoResolution);
- }
-
- Indicator {
- id: wbIndicator
- source: visible ? "image://theme/" + Data.wbIcon(settings.videoWhiteBalance) + "-screen" : ""
- visible: settings.videoWhiteBalance != WhiteBalance.Auto
- }
-
- Indicator {
- id: cfIndicator
- source: "image://theme/" + Data.cfIcon(settings.videoColorFilter) + "-screen"
- visible: settings.videoColorFilter != ColorTone.Normal
- }
-
- Indicator {
- id: gpsIndicator
- visible: settings.useGps
- source: "image://theme/icon-m-camera-location"
-
- PropertyAnimation on opacity {
- easing.type: Easing.OutSine
- loops: Animation.Infinite
- from: 0.2
- to: 1.0
- duration: 1000
- running: settings.useGps && !positionSource.position.longitudeValid
- alwaysRunToEnd: true
- }
- }
- }
- }
-
- Button {
- id: cameraRoll
- anchors.top: parent.top
- anchors.right: parent.right
- anchors.topMargin: 20
- anchors.rightMargin: 20
- width: 56
- height: 56
-
- opacity: 0.5
- iconSource: "image://theme/icon-m-camera-roll"
- onClicked: openFile("PostCapturePage.qml");
- visible: controlsVisible
- }
-
- CameraToolBar {
- id: toolBar
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 20
- anchors.left: parent.left
- anchors.leftMargin: 20
- opacity: 0.5
- targetWidth: parent.width - (anchors.leftMargin * 2) - (66 * 1.5)
- visible: controlsVisible
- expanded: settings.showToolBar
- onExpandedChanged: settings.showToolBar = expanded;
-
- items: [
- VideoTorchButton {
- camera: cam
- },
- VideoSceneButton {
- onClicked: toolBar.push(items);
- },
- VideoEvCompButton {
- onClicked: toolBar.push(items);
- },
- VideoWhiteBalanceButton {
- onClicked: toolBar.push(items);
- },
- VideoColorFilterButton {
- onClicked: toolBar.push(items);
- },
- VideoMuteButton {
- },
- ToolIcon {
- iconSource: "image://theme/icon-m-toolbar-view-menu-white"
- onClicked: openSettings();
- }
- ]
- }
-
- function openSettings() {
- if (!settingsDialog) {
- settingsDialog = videoSettingsDialog.createObject(page);
- }
-
- settingsDialog.open();
- }
-
- Component {
- id: videoSettingsDialog
-
- VideoSettingsDialog { }
- }
-}
// TODO: error reporting
-CameraPage {
- id: page
-
- property bool popTwice: false
- controlsVisible: false
- policyMode: CameraResources.None
- activationData: ControlsActivationData {standbyVisible: false}
-
- property alias source: video.source
-
- function play() {
- video.play();
+Item {
+ id: page
+
+ signal finished
+ property alias source: video.source
+
+ function play() {
+ video.play()
+ }
+
+ MouseArea {
+ anchors.top: parent.top
+ anchors.bottom: toolBar.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ onClicked: toolBar.show = !toolBar.show
+ }
+
+ Timer {
+ id: hideTimer
+ running: toolBar.show
+ interval: 3000
+ onTriggered: toolBar.show = false
+ }
+
+ Video {
+ id: video
+ anchors.fill: parent
+
+ function toggle() {
+ if (!video.paused) {
+ video.pause()
+ } else {
+ page.play()
+ }
}
- MouseArea {
- anchors.top: parent.top
- anchors.bottom: toolBar.top
- anchors.left: parent.left
- anchors.right: parent.right
+ onStopped: page.finished()
+ }
- onClicked: toolBar.show = !toolBar.show
+ Connections {
+ target: Qt.application
+ onActiveChanged: {
+ if (!Qt.application.active) {
+ video.stop()
+ }
}
+ }
- Timer {
- id: hideTimer
- running: toolBar.show
- interval: 3000
- onTriggered: toolBar.show = false;
- }
+ CameraToolBar {
+ id: toolBar
- Video {
- id: video
- anchors.fill: parent
-
- function toggle() {
- if (!video.paused) {
- video.pause();
- }
- else {
- page.play();
- }
- }
+ property bool show: true
- onStopped: {
- source = "";
- pageStack.pop(undefined, true);
+ manualBack: true
+ expanded: true
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: show ? 20 : -1 * (height + 20)
+ anchors.left: parent.left
+ anchors.leftMargin: 20
+ opacity: 0.5
- if (page.popTwice) {
- pageStack.pop(undefined);
- }
- }
- }
-
- Connections {
- target: Qt.application
- onActiveChanged: {
- if (!Qt.application.active) {
- video.stop();
- }
- }
+ Behavior on anchors.bottomMargin {
+ PropertyAnimation { duration: 200; }
}
- CameraToolBar {
- id: toolBar
+ items: [
+ ToolIcon {
+ iconId: "icon-m-toolbar-mediacontrol-stop-white"
+ onClicked: video.stop()
+ },
+ Slider {
+ id: slider
+ height: toolBar.height
+ anchors.verticalCenter: parent.verticalCenter
+
+ platformStyle: SliderStyle {
+ handleBackground: ""
+ handleBackgroundPressed: ""
+ }
- property bool show: true
+ minimumValue: 0
+ maximumValue: video.duration
+ value: video.position
+ orientation: Qt.Horizontal
- manualBack: true
- expanded: true
- anchors.bottom: parent.bottom
- anchors.bottomMargin: show ? 20 : -1 * (height + 20)
- anchors.left: parent.left
- anchors.leftMargin: 20
- opacity: 0.5
+ onPressedChanged: {
+ if (!slider.pressed) {
+ video.position = slider.value
+ }
- Behavior on anchors.bottomMargin {
- PropertyAnimation { duration: 200; }
+ hideTimer.restart()
}
-
+ },
+ ToolIcon {
+ id: control
+ iconId: !video.paused ? "icon-m-toolbar-mediacontrol-pause-white" : "icon-m-toolbar-mediacontrol-play-white"
onClicked: {
- page.popTwice = true;
- video.stop();
+ video.toggle()
+ hideTimer.restart()
}
-
- items: [
- ToolIcon { iconId: "icon-m-toolbar-mediacontrol-stop-white"; onClicked: { video.stop(); } },
- Slider {
- id: slider
- height: toolBar.height
- anchors.verticalCenter: parent.verticalCenter
-
- platformStyle: SliderStyle {
- handleBackground: ""
- handleBackgroundPressed: ""
- }
-
- minimumValue: 0
- maximumValue: video.duration
- value: video.position
- orientation: Qt.Horizontal
-
- onPressedChanged: {
- if (!slider.pressed) {
- video.position = slider.value;
- }
-
- hideTimer.restart();
- }
- },
- ToolIcon {
- id: control
- iconId: !video.paused ? "icon-m-toolbar-mediacontrol-pause-white" : "icon-m-toolbar-mediacontrol-play-white"
- onClicked: {
- video.toggle();
- hideTimer.restart();
- }
- }
- ]
- }
+ }
+ ]
+ }
}
import com.nokia.meego 1.1
Column {
- spacing: 10
-
- SectionHeader {
- text: qsTr("Resolution");
- }
+ spacing: 10
+ SectionHeader {
+ text: qsTr("Resolution")
+ }
- ButtonRow {
- width: parent.width
- enabled: cam.idle
- exclusive: false
+ ButtonRow {
+ width: parent.width
+ enabled: cam.idle
+ exclusive: false
- Repeater {
- id: resolutions
+ Repeater {
+ id: resolutions
- model: videoSettings.resolutions
+ model: videoSettings.resolutions
- delegate: Button {
- font.capitalization: Font.Capitalize
- text: qsTr("%1 %2").arg(resolutionName).arg(resolution);
- checked: settings.videoResolution == resolutionName;
- onClicked: settings.videoResolution = resolutionName;
- }
- }
+ delegate: Button {
+ font.capitalization: Font.Capitalize
+ text: qsTr("%1 %2").arg(resolutionName).arg(resolution)
+ checked: settings.videoResolution == resolutionName
+ onClicked: settings.videoResolution = resolutionName
+ }
}
+ }
}
--- /dev/null
+// -*- qml -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+import QtQuick 1.1
+import com.nokia.meego 1.1
+import QtCamera 1.0
+
+Flickable {
+ contentHeight: col.height
+ anchors.fill: parent
+ anchors.margins: 10
+
+ Column {
+ id: col
+ width: parent.width
+ spacing: 10
+
+ Label {
+ font.pixelSize: 36
+ text: qsTr("Video settings")
+ }
+
+ VideoResolutionSettings {
+ width: parent.width
+ }
+
+ CameraSettings {
+ anchors.horizontalCenter: parent.horizontalCenter
+ }
+ }
+}
+++ /dev/null
-// -*- qml -*-
-
-/*!
- * This file is part of CameraPlus.
- *
- * 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
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-import QtQuick 1.1
-import com.nokia.meego 1.1
-import QtCamera 1.0
-
-Dialog {
- id: dialog
-
- content: item
-
- Connections {
- target: Qt.application
- onActiveChanged: {
- if (!Qt.application.active) {
- dialog.close();
- }
- }
- }
-
- onStatusChanged: {
- if (status == DialogStatus.Open) {
- cam.renderingEnabled = false;
- }
- else if (status == DialogStatus.Closing) {
- cam.renderingEnabled = true;
- }
- }
-
- Item {
- id: item
- width: parent.width
- height: root.height
-
-
- Flickable {
- id: flickable
- anchors.fill: parent
- anchors.margins: 10
- contentHeight: col.height
-
- Column {
- id: col
-
- width: parent.width
- spacing: 10
-
- Label {
- font.pixelSize: 36
- text: qsTr("Video settings");
- }
-
- VideoResolutionSettings {
- width: parent.width
- }
-
- CameraSettings {
- anchors.horizontalCenter: parent.horizontalCenter
- }
- }
- }
- }
-}
import CameraPlus 1.0
Item {
- id: zoomHandler
- property Item page
- property bool zoomPressed: false
+ id: zoomHandler
+ property bool zoomPressed: false
- signal pressed();
- signal released();
+ signal pressed()
+ signal released()
- property bool active: settings.zoomAsShutter && page.status == PageStatus.Active && Qt.application.active
+ property bool active: settings.zoomAsShutter && Qt.application.active
- function handlePress() {
- if (!zoomHandler.active || zoomHandler.zoomPressed) {
- return;
- }
-
- zoomHandler.zoomPressed = true;
- zoomHandler.pressed();
+ function handlePress() {
+ if (!zoomHandler.active || zoomHandler.zoomPressed) {
+ return
}
- function handleRelease() {
- if (!zoomHandler.active || !zoomHandler.zoomPressed) {
- return;
- }
-
- zoomHandler.zoomPressed = false;
+ zoomHandler.zoomPressed = true
+ zoomHandler.pressed()
+ }
- zoomHandler.released();
+ function handleRelease() {
+ if (!zoomHandler.active || !zoomHandler.zoomPressed) {
+ return
}
- Connections {
- id: zoomConnection
- target: keys
+ zoomHandler.zoomPressed = false
- onActiveChanged: {
- if (!zoomConnection.active) {
- zoomHandler.zoomPressed = false;
- }
- }
+ zoomHandler.released()
+ }
- onVolumeUpPressed: zoomHandler.handlePress();
- onVolumeDownPressed: zoomHandler.handlePress();
- onVolumeUpReleased: zoomHandler.handleRelease();
- onVolumeDownReleased: zoomHandler.handleRelease();
+ Connections {
+ id: zoomConnection
+ target: keys
+
+ onActiveChanged: {
+ if (!zoomConnection.active) {
+ zoomHandler.zoomPressed = false
+ }
}
- Connections {
- target: Qt.application
- onActiveChanged: {
- if (!Qt.application.active) {
- zoomHandler.zoomPressed = false;
- }
- }
+ onVolumeUpPressed: zoomHandler.handlePress()
+ onVolumeDownPressed: zoomHandler.handlePress()
+ onVolumeUpReleased: zoomHandler.handleRelease()
+ onVolumeDownReleased: zoomHandler.handleRelease()
+ }
+
+ Connections {
+ target: Qt.application
+ onActiveChanged: {
+ if (!Qt.application.active) {
+ zoomHandler.zoomPressed = false
+ }
}
+ }
}
import CameraPlus 1.0
MouseArea {
- id: zoomCancel
- property Item page
- property Item zoomCapture
+ id: zoomCancel
+ property Item zoomCapture
- signal canceled
+ signal canceled
- z: 100
- enabled: zoomCapture.zoomPressed
+ z: 100
+ enabled: zoomCapture.zoomPressed
- onPressed: {
- zoomCancel.zoomCapture.zoomPressed = false;
- zoomCancel.canceled();
- }
+ onPressed: {
+ zoomCancel.zoomCapture.zoomPressed = false
+ zoomCancel.canceled()
+ }
- Rectangle {
- anchors.top: parent.top
- opacity: parent.enabled ? 0.5 : 0
- anchors.topMargin: 20
- anchors.horizontalCenter: parent.horizontalCenter
- visible: opacity > 0
- height: label.height * 2
- width: parent.width * 0.7
- color: "black"
- border.color: "gray"
- radius: 20
+ Rectangle {
+ anchors.top: parent.top
+ opacity: parent.enabled ? 0.5 : 0
+ anchors.topMargin: 20
+ anchors.horizontalCenter: parent.horizontalCenter
+ visible: opacity > 0
+ height: label.height * 2
+ width: parent.width * 0.7
+ color: "black"
+ border.color: "gray"
+ radius: 20
- Behavior on opacity {
- PropertyAnimation { duration: 100; }
- }
+ Behavior on opacity {
+ PropertyAnimation { duration: 100; }
+ }
- Label {
- id: label
- anchors.verticalCenter: parent.verticalCenter
- width: parent.width
- text: qsTr("Tap anywhere to cancel");
- font.pixelSize: 24
- horizontalAlignment: Text.AlignHCenter
- }
+ Label {
+ id: label
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width
+ text: qsTr("Tap anywhere to cancel")
+ font.pixelSize: 24
+ horizontalAlignment: Text.AlignHCenter
}
+ }
}
import QtCamera 1.0
Slider {
- id: slider
- property Camera camera: null
+ id: slider
+ property Camera camera: null
- platformStyle: SliderStyle {
- handleBackground: ""
- handleBackgroundPressed: ""
- }
+ platformStyle: SliderStyle {
+ handleBackground: ""
+ handleBackgroundPressed: ""
+ }
- Binding {
- target: camera.zoom
- property: "value"
- value: slider.value
- }
+ Binding {
+ target: camera.zoom
+ property: "value"
+ value: slider.value
+ }
- Connections {
- target: camera
- onModeChanged: slider.value = camera.zoom.minimum;
- }
+ Connections {
+ target: camera
+ onModeChanged: slider.value = camera.zoom.minimum;
+ }
- Connections {
- target: keys
+ Connections {
+ target: keys
- onVolumeUpPressed: {
- if (settings.zoomAsShutter) {
- return;
- }
+ onVolumeUpPressed: {
+ if (settings.zoomAsShutter) {
+ return;
+ }
- slider.value = Math.min(slider.value + slider.stepSize, slider.maximumValue);
- hackTimer.running = true;
- }
+ slider.value = Math.min(slider.value + slider.stepSize, slider.maximumValue)
+ hackTimer.running = true
+ }
- onVolumeDownPressed: {
- if (settings.zoomAsShutter) {
- return;
- }
+ onVolumeDownPressed: {
+ if (settings.zoomAsShutter) {
+ return;
+ }
- slider.value = Math.max(slider.value - slider.stepSize, slider.minimumValue);
- hackTimer.running = true;
- }
+ slider.value = Math.max(slider.value - slider.stepSize, slider.minimumValue)
+ hackTimer.running = true
}
+ }
- orientation: Qt.Horizontal
- width: 500
- height: 50
- stepSize:0.1
- value: camera.zoom.value
- minimumValue: camera.zoom.minimum
- maximumValue: camera.zoom.maximum
+ orientation: Qt.Horizontal
+ width: 500
+ height: 50
+ stepSize:0.1
+ value: camera.zoom.value
+ minimumValue: camera.zoom.minimum
+ maximumValue: camera.zoom.maximum
- state: "hidden"
- states: [
+ state: "hidden"
+ states: [
State {
- name: "visible"
- when: slider.pressed || hackTimer.running
- PropertyChanges { target: slider; opacity: 1.0 }
+ name: "visible"
+ when: slider.pressed || hackTimer.running
+ PropertyChanges { target: slider; opacity: 1.0 }
},
State {
- name: "hidden"
- when: !slider.pressed
- PropertyChanges { target: slider; opacity: 0.2 }
- }]
-
- transitions: Transition {
- to: "hidden"
- SequentialAnimation {
- PauseAnimation { duration: 2000 }
- NumberAnimation { target: slider; property: "opacity"; duration: 250 }
- }
+ name: "hidden"
+ when: !slider.pressed
+ PropertyChanges { target: slider; opacity: 0.2 }
}
+ ]
- Timer {
- id: hackTimer
- interval: 1
- }
+ transitions: Transition {
+ to: "hidden"
+ SequentialAnimation {
+ PauseAnimation { duration: 2000 }
+ NumberAnimation { target: slider; property: "opacity"; duration: 250 }
+ }
+ }
+
+ Timer {
+ id: hackTimer
+ interval: 1
+ }
}
import QtCamera 1.0
import CameraPlus 1.0
import QtMobility.location 1.2
-
+//import QtCamera 1.0
// TODO: flash not ready (battery low or flash not ready message)
Window {
id: root
+ property alias camera: cam
+// property bool cameraVisible: mainView.currentIndex == 1
- property alias dimmer: camDimmer
+ VisualItemModel {
+ id: mainModel
- PageStack {
- id: pageStack
- anchors.fill: parent
+ SettingsView {
+ width: mainView.width
+ height: mainView.height
+ }
+
+ CameraView {
+ id: cam
+ width: mainView.width
+ height: mainView.height
+ }
+
+ PostCaptureView {
+ width: mainView.width
+ height: mainView.height
+ }
}
- MouseArea {
- anchors.fill: parent
- enabled: pageStack.busy
+ ListView {
+ id: mainView
+ LayoutMirroring.enabled: false
+ anchors.fill: parent
+ orientation: ListView.Horizontal
+ model: mainModel
+ snapMode: ListView.SnapOneItem
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ boundsBehavior: Flickable.StopAtBounds
+ currentIndex: 1
+ interactive: !currentItem.pressed
+ }
+
+ Component.onCompleted: {
+ screen.setAllowedOrientations(Screen.Landscape)
+ theme.inverted = true
+ platformSettings.init()
+ // TODO: hardcoding device id
+ root.resetCamera(0, settings.mode)
}
PlatformSettings {
- id: platformSettings
+ id: platformSettings
}
- Component.onCompleted: {
- platformSettings.init();
- theme.inverted = true;
- // TODO: hardcoding device id
- root.resetCamera(0, settings.mode);
+ Settings {
+ id: settings
}
- function showError(msg) {
- error.text = msg;
- error.show();
+ PipelineManager {
+ id: pipelineManager
+ camera: cam
+ currentItem: mainView.currentItem
}
function resetCamera(deviceId, mode) {
- if (!cam.reset(deviceId, mode)) {
- showError(qsTr("Failed to set camera device and mode. Please restart the application."));
- }
+ if (!cam.reset(deviceId, mode)) {
+ showError(qsTr("Failed to set camera device and mode. Please restart the application."))
+ }
+ }
+
+ function showError(msg) {
+ error.text = msg
+ error.show()
+ }
+
+ property alias dimmer: camDimmer
+
+ PageStack {
+ id: pageStack
+ anchors.fill: parent
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ enabled: pageStack.busy
}
PositionSource {
- // NOTE: The source will not reset the position when we lose the signal.
- // This shouldn't be a big problem as we are course enough.
- // If we ever need street level updates then this will be an issue.
- id: positionSource
- active: settings.useGps
- // TODO: we cannot bind to cam.running because camera will stop
- // when the connection dialog pops up and we end up with an infinite loop
- // active: cam.running && settings.useGps
- onPositionChanged: geocode.search(position.coordinate.longitude, position.coordinate.latitude);
+ // NOTE: The source will not reset the position when we lose the signal.
+ // This shouldn't be a big problem as we are course enough.
+ // If we ever need street level updates then this will be an issue.
+ id: positionSource
+ active: settings.useGps
+ // TODO: we cannot bind to cam.running because camera will stop
+ // when the connection dialog pops up and we end up with an infinite loop
+ // active: cam.running && settings.useGps
+ onPositionChanged: geocode.search(position.coordinate.longitude, position.coordinate.latitude)
}
MetaData {
- id: metaData
- camera: cam
- manufacturer: deviceInfo.manufacturer
- model: deviceInfo.model
- country: geocode.country
- city: geocode.city
- suburb: geocode.suburb
- longitude: positionSource.position.coordinate.longitude
- longitudeValid: positionSource.position.longitudeValid && settings.useGps
- latitude: positionSource.position.coordinate.latitude
- latitudeValid: positionSource.position.latitudeValid && settings.useGps
- elevation: positionSource.position.coordinate.altitude
- elevationValid: positionSource.position.altitudeValid && settings.useGps
- orientation: orientation.orientation
- artist: settings.creatorName
- captureDirection: compass.direction
- captureDirectionValid: compass.directionValid
- horizontalError: positionSource.position.horizontalAccuracy
- horizontalErrorValid: positionSource.position.horizontalAccuracyValid && settings.useGps
- dateTimeEnabled: true
+ id: metaData
+ camera: cam
+ manufacturer: deviceInfo.manufacturer
+ model: deviceInfo.model
+ country: geocode.country
+ city: geocode.city
+ suburb: geocode.suburb
+ longitude: positionSource.position.coordinate.longitude
+ longitudeValid: positionSource.position.longitudeValid && settings.useGps
+ latitude: positionSource.position.coordinate.latitude
+ latitudeValid: positionSource.position.latitudeValid && settings.useGps
+ elevation: positionSource.position.coordinate.altitude
+ elevationValid: positionSource.position.altitudeValid && settings.useGps
+ orientation: orientation.orientation
+ artist: settings.creatorName
+ captureDirection: compass.direction
+ captureDirectionValid: compass.directionValid
+ horizontalError: positionSource.position.horizontalAccuracy
+ horizontalErrorValid: positionSource.position.horizontalAccuracyValid && settings.useGps
+ dateTimeEnabled: true
}
Orientation {
- id: orientation
- active: cam.running
+ id: orientation
+ active: cam.running
}
Compass {
- id: compass
- active: cam.running
+ id: compass
+ active: cam.running
}
ReverseGeocode {
- id: geocode
- active: cam.running && settings.useGps && settings.useGeotags
- }
-
- PipelineManager {
- id: pipelineManager
- camera: cam
+ id: geocode
+ active: cam.running && settings.useGps && settings.useGeotags
}
DeviceInfo {
- id: deviceInfo
+ id: deviceInfo
}
FSMonitor {
- id: fileSystem
+ id: fileSystem
}
InfoBanner {
- id: error
- }
-
- Settings {
- id: settings
+ id: error
}
FileNaming {
- id: fileNaming
- imageSuffix: cam.imageSuffix
- videoSuffix: cam.videoSuffix
+ id: fileNaming
+ imageSuffix: cam.imageSuffix
+ videoSuffix: cam.videoSuffix
}
MountProtector {
- id: mountProtector
- path: fileNaming.path
- }
-
- BatteryInfo {
- id: batteryMonitor
- active: cam.running
-
- function check() {
- if (!checkBattery()) {
- pageStack.currentPage.batteryLow();
- }
- }
-
- onChargingChanged: {
- batteryMonitor.check();
- }
-
- onCriticalChanged: {
- batteryMonitor.check();
- }
- }
-
- function replacePage(file) {
- pageStack.replace(Qt.resolvedUrl(file), {cam: cam, dimmer: root.dimmer}, true);
+ id: mountProtector
+ path: fileNaming.path
}
- function openFile(file) {
- pageStack.push(Qt.resolvedUrl(file), {cam: cam, dimmer: root.dimmer});
- }
-
- function openFileNow(file) {
- pageStack.push(Qt.resolvedUrl(file), {cam: cam, dimmer: root.dimmer}, true);
+ TrackerStore {
+ id: trackerStore
+ active: cam.running
+ manufacturer: deviceInfo.manufacturer
+ model: deviceInfo.model
}
- function checkBattery() {
- // We are fine if we are connected to the charger:
- if (batteryMonitor.charging) {
- return true;
- }
-
- // If we have enough battery then we are fine:
- if (!batteryMonitor.critical) {
- return true;
- }
-
- return false;
+ function checkDiskSpace() {
+ return fileSystem.hasFreeSpace(fileNaming.path)
}
ImageSettings {
- id: imageSettings
- camera: cam
- function setImageResolution() {
- if (!imageSettings.setResolution(settings.imageAspectRatio, settings.imageResolution)) {
- showError(qsTr("Failed to set required resolution"));
- }
+ id: imageSettings
+ camera: cam
+ function setImageResolution() {
+ if (!imageSettings.setResolution(settings.imageAspectRatio, settings.imageResolution)) {
+ showError(qsTr("Failed to set required resolution"))
}
+ }
- onReadyChanged: {
- if (ready) {
- imageSettings.setImageResolution();
- }
+ onReadyChanged: {
+ if (ready) {
+ imageSettings.setImageResolution()
}
+ }
}
VideoSettings {
- id: videoSettings
- camera: cam
+ id: videoSettings
+ camera: cam
- function setVideoResolution() {
- if (!videoSettings.setResolution(settings.videoAspectRatio, settings.videoResolution)) {
- showError(qsTr("Failed to set required resolution"));
- }
+ function setVideoResolution() {
+ if (!videoSettings.setResolution(settings.videoAspectRatio, settings.videoResolution)) {
+ showError(qsTr("Failed to set required resolution"))
}
+ }
- onReadyChanged: {
- if (ready) {
- videoSettings.setVideoResolution();
- }
+ onReadyChanged: {
+ if (ready) {
+ videoSettings.setVideoResolution()
}
+ }
}
Connections {
- target: settings
-
- onImageAspectRatioChanged: {
- imageSettings.setImageResolution();
- }
-
- onImageResolutionChanged: {
- imageSettings.setImageResolution();
- }
-
- onVideoResolutionChanged: {
- videoSettings.setVideoResolution();
- }
- }
-
- Camera {
- id: cam
- anchors.fill: parent
-
- onRoiChanged: roi.normalize = false;
-
- GridLines {
- x: cam.renderArea.x
- y: cam.renderArea.y
- width: cam.renderArea.width
- height: cam.renderArea.height
- visible: settings.gridEnabled
- }
-
- FocusReticle {
- id: focusReticle
- cam: cam
- visible: pageStack.currentPage && pageStack.currentPage.controlsVisible && pageStack.currentPage.focusReticleVisible && cam && cam.autoFocus.canFocus(cam.scene.value);
- cafStatus: cam ? cam.autoFocus.cafStatus : -1
- status: cam ? cam.autoFocus.status : -1
- }
-
- onError: {
- if (pipelineManager.error) {
- // Ignore any subsequent errors.
- // Killing pulseaudio while recording will lead to an
- // infinite supply of errors which will break the UI
- // if we show a banner for each.
- return;
- }
-
- pipelineManager.error = true;
- pageStack.currentPage.cameraError();
- console.log("Camera error (" + code + "): " + message + " " + debug);
- showError(qsTr("Camera error. Please restart the application."));
-
- // We cannot stop camera here. Seems there is a race condition somewhere
- // which leads to a freeze if we do so.
- }
-
- onRunningChanged: {
- if (!cam.running) {
- mountProtector.unlock();
- }
- }
-
- Component.onDestruction: cam.stop();
-
- // We need to show viewfinder below pages.
- z: -1
-
- Rectangle {
- property bool dimmed: false
- id: camDimmer
- z: 1
- anchors.fill: parent
- opacity: dimmed ? 1.0 : 0.0
- color: "black"
- Behavior on opacity {
- PropertyAnimation { duration: 150 }
- }
- }
+ target: settings
- notifications: Sounds {
- id: sounds
- mute: !settings.soundEnabled
- }
-
- }
-
- Binding {
- target: cam.flash
- property: "value"
- when: cam.mode == Camera.ImageMode
- value: settings.imageFlashMode
- }
-
- Binding {
- target: settings
- property: "imageFlashMode"
- when: cam.mode == Camera.ImageMode
- value: cam.flash.value
- }
+ onImageAspectRatioChanged: {
+ imageSettings.setImageResolution()
+ }
- Binding {
- target: cam.scene
- property: "value"
- when: cam.mode == Camera.VideoMode
- value: settings.videoSceneMode
- }
-
- Binding {
- target: cam.scene
- property: "value"
- when: cam.mode == Camera.ImageMode
- value: settings.imageSceneMode
- }
-
- Binding {
- target: cam.evComp
- property: "value"
- when: cam.mode == Camera.ImageMode
- value: settings.imageEvComp
- }
-
- Binding {
- target: cam.evComp
- property: "value"
- when: cam.mode == Camera.VideoMode
- value: settings.videoEvComp
- }
+ onImageResolutionChanged: {
+ imageSettings.setImageResolution()
+ }
- Binding {
- target: settings
- property: "imageEvComp"
- when: cam.mode == Camera.ImageMode
- value: cam.evComp.value
- }
-
- Binding {
- target: settings
- property: "videoEvComp"
- when: cam.mode == Camera.VideoMode
- value: cam.evComp.value
- }
-
- Binding {
- target: cam.whiteBalance
- property: "value"
- when: cam.mode == Camera.ImageMode
- value: settings.imageWhiteBalance
- }
-
- Binding {
- target: cam.whiteBalance
- property: "value"
- when: cam.mode == Camera.VideoMode
- value: settings.videoWhiteBalance
- }
-
- Binding {
- target: cam.colorTone
- property: "value"
- when: cam.mode == Camera.ImageMode
- value: settings.imageColorFilter
- }
-
- Binding {
- target: cam.colorTone
- property: "value"
- when: cam.mode == Camera.VideoMode
- value: settings.videoColorFilter
- }
-
- Binding {
- target: cam.iso
- property: "value"
- when: cam.mode == Camera.ImageMode
- value: settings.imageIso
- }
-
- Binding {
- target: settings
- property: "imageIso"
- when: cam.mode == Camera.ImageMode
- value: cam.iso.value
- }
-
- Binding {
- target: cam.videoMute
- property: "enabled"
- value: settings.videoMuted
- }
-
- Binding {
- target: cam.roi
- property: "enabled"
- value: settings.faceDetectionEnabled && !focusReticle.pressed && !focusReticle.touchMode && cam.mode == Camera.ImageMode
- }
-
-
- TrackerStore {
- id: trackerStore
- active: cam.running
- manufacturer: deviceInfo.manufacturer
- model: deviceInfo.model
+ onVideoResolutionChanged: {
+ videoSettings.setVideoResolution()
+ }
}
ModeController {
- id: cameraMode
- cam: cam
- dimmer: root.dimmer
- }
-
- Connections {
- target: cam
- onModeChanged: {
- if (cam.mode == Camera.VideoMode) {
- replacePage("VideoPage.qml");
- }
- else {
- replacePage("ImagePage.qml");
- }
- }
+ id: cameraMode
+ cam: cam
+ dimmer: root.dimmer
}
- Standby {
- policyLost: pipelineManager.state == "policyLost"
- show: !pageStack.currentPage || (pageStack.currentPage.activationData.standbyVisible && pageStack.currentPage.status == PageStatus.Active && pipelineManager.showStandBy)
+ Rectangle {
+ property bool dimmed: false
+ id: camDimmer
+ z: 1
+ anchors.fill: parent
+ opacity: dimmed ? 1.0 : 0.0
+ color: "black"
+ Behavior on opacity {
+ PropertyAnimation { duration: 150 }
+ }
}
DeviceKeys {
- id: keys
- active: Qt.application.active && pipelineManager.scaleAcquired
- repeat: !settings.zoomAsShutter
+ id: keys
+ active: Qt.application.active && pipelineManager.scaleAcquired
+ repeat: !settings.zoomAsShutter
}
+
+// Standby {
+// policyLost: pipelineManager.state == "policyLost"
+// TODO:
+// show: !pageStack.currentPage || (pageStack.currentPage.activationData.standbyVisible && pageStack.currentPage.status == PageStatus.Active && pipelineManager.showStandBy)
+// }
}
<RCC version="1.0">
<qresource prefix="/qml">
<file>main.qml</file>
+ <file>SettingsView.qml</file>
+ <file>CameraView.qml</file>
+ <file>CameraOverlay.qml</file>
+ <file>ImageOverlay.qml</file>
+ <file>VideoOverlay.qml</file>
+ <file>RecordingDurationLabel.qml</file>
+ <file>PostCaptureView.qml</file>
<file>PipelineManager.qml</file>
<file>FocusReticle.qml</file>
- <file>CameraPage.qml</file>
- <file>ControlsActivationData.qml</file>
- <file>Standby.qml</file>
- <file>CameraSettings.qml</file>
- <file>VideoPage.qml</file>
- <file>ImagePage.qml</file>
<file>ZoomSlider.qml</file>
- <file>RecordingPage.qml</file>
<file>ModeController.qml</file>
<file>ModeButton.qml</file>
<file>CaptureButton.qml</file>
<file>CameraToolBar.qml</file>
<file>CameraToolBar.js</file>
<file>data.js</file>
+ <file>PreviewImage.qml</file>
+ <file>ImageSettings.qml</file>
+ <file>VideoSettings.qml</file>
+ <file>ImageResolutionSettings.qml</file>
+ <file>VideoResolutionSettings.qml</file>
+ <file>SectionHeader.qml</file>
+ <file>TextSwitch.qml</file>
+ <file>CameraSettings.qml</file>
+ <file>ZoomCaptureButton.qml</file>
+ <file>ZoomCaptureCancel.qml</file>
+ <file>PostCaptureItem.qml</file>
+
+ <file>CameraPage.qml</file>
+ <file>Standby.qml</file>
<file>FlashButton.qml</file>
<file>ImageSceneButton.qml</file>
<file>ImageEvCompButton.qml</file>
<file>ImageWhiteBalanceButton.qml</file>
<file>ImageColorFilterButton.qml</file>
<file>ImageIsoButton.qml</file>
- <file>PreviewImage.qml</file>
<file>CheckButton.qml</file>
<file>VideoTorchButton.qml</file>
- <file>PostCaptureItem.qml</file>
- <file>PostCapturePage.qml</file>
<file>VideoSceneButton.qml</file>
<file>VideoEvCompButton.qml</file>
<file>VideoWhiteBalanceButton.qml</file>
<file>VideoColorFilterButton.qml</file>
<file>VideoMuteButton.qml</file>
<file>VideoPlayerPage.qml</file>
- <file>SectionHeader.qml</file>
- <file>TextSwitch.qml</file>
- <file>ImageSettingsDialog.qml</file>
- <file>ImageResolutionSettings.qml</file>
- <file>VideoSettingsDialog.qml</file>
- <file>VideoResolutionSettings.qml</file>
- <file>ZoomCaptureButton.qml</file>
- <file>ZoomCaptureCancel.qml</file>
</qresource>
</RCC>