// -*- 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 com.nokia.extras 1.1
import QtCamera 1.0
import CameraPlus 1.0
-import QtMobility.systeminfo 1.2
-
-// TODO: metadata creator name, gps, geotags
-// TODO: resolutions and aspect ratios
-// TODO: postcapture
-// TODO: battery low state
-// TODO: disk space
-// TODO: flash not ready
-// TODO: focus, caf, ...
-// TODO: indicators
-// TODO: portrait/landscape
-// TODO: record video in a hidden directory and then copy the video to avoid tracker indexing it.
-// TODO: stop viewfinder in postcapture and settings pages ?
-// TODO: resource policy
-// TODO: prevent going to mass storage while recording and capturing
-// TODO: sounds
-// TODO: grid lines, face tracking
-// TODO: complete settings pages
-// TODO: stop camera properly when we get closed.
-// TODO: select primary/secondary camera.
-// TODO: disable debug builds.
-// TODO: seems start gets called when we are shutting down
-// TODO: seems start gets called twice when we are starting up if screen is locked or dimmed ?!
-
-PageStackWindow {
+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
- showStatusBar: false
+ SettingsView {
+ width: mainView.width
+ height: mainView.height
+ }
+
+ CameraView {
+ id: cam
+ width: mainView.width
+ height: mainView.height
+ }
+
+ PostCaptureView {
+ width: mainView.width
+ height: mainView.height
+ }
+ }
+
+ 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: {
- theme.inverted = true;
- if (settings.mode == 0) {
- openFile("ImagePage.qml");
- }
- else {
- openFile("VideoPage.qml");
- }
+ screen.setAllowedOrientations(Screen.Landscape)
+ theme.inverted = true
+ platformSettings.init()
+ // TODO: hardcoding device id
+ root.resetCamera(0, settings.mode)
+ }
+
+ PlatformSettings {
+ id: platformSettings
+ }
+
+ Settings {
+ id: settings
+ }
+
+ 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."))
+ }
}
function showError(msg) {
- error.text = msg;
- error.show();
- }
-
- CameraResources {
- id: resourcePolicy
- onAcquiredChanged: {
- if (resourcePolicy.acquired) {
- // TODO:
- }
- else {
- // TODO: We need a way to force a stop.
- }
- }
+ 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)
+ }
+
+ 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
+ }
+
+ Orientation {
+ id: orientation
+ active: cam.running
+ }
+
+ Compass {
+ id: compass
+ active: cam.running
+ }
+
+ ReverseGeocode {
+ 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
}
- // Stolen from https://qt.gitorious.org/qt-components/qt-components/blobs/master/examples/meego/QmlComponentGallery/qml/ListPage.qml
- function replacePage(file) {
- var component = Qt.createComponent(file)
+ MountProtector {
+ id: mountProtector
+ path: fileNaming.path
+ }
- if (component.status == Component.Ready) {
- pageStack.replace(component, {cam: cam}, true);
- }
- else {
- console.log("Error loading component:", component.errorString());
- }
+ TrackerStore {
+ id: trackerStore
+ active: cam.running
+ manufacturer: deviceInfo.manufacturer
+ model: deviceInfo.model
}
- function openFile(file) {
- var component = Qt.createComponent(file)
+ function checkDiskSpace() {
+ return fileSystem.hasFreeSpace(fileNaming.path)
+ }
- if (component.status == Component.Ready) {
- pageStack.push(component, {cam: cam});
+ ImageSettings {
+ id: imageSettings
+ camera: cam
+ function setImageResolution() {
+ if (!imageSettings.setResolution(settings.imageAspectRatio, settings.imageResolution)) {
+ showError(qsTr("Failed to set required resolution"))
}
- else {
- console.log("Error loading component:", component.errorString());
+ }
+
+ onReadyChanged: {
+ if (ready) {
+ imageSettings.setImageResolution()
}
+ }
}
- platformStyle: PageStackWindowStyle {
- // TODO: Hack
- background: " "
- }
+ VideoSettings {
+ id: videoSettings
+ camera: cam
- Camera {
-/*
- onDeviceIdChanged: {
- // TODO: is this needed ?
- if (platformWindow.active) {
- cam.start();
- }
+ function setVideoResolution() {
+ if (!videoSettings.setResolution(settings.videoAspectRatio, settings.videoResolution)) {
+ showError(qsTr("Failed to set required resolution"))
}
-*/
- id: cam
- anchors.fill: parent
-
- // TODO: hardcoding device id
- Component.onCompleted: { cam.deviceId = 0; mode = settings.mode; }
+ }
- // TODO: Hack
- z: -1
-
- Rectangle {
- id: camDimmer
- z: 1
- anchors.fill: parent
- opacity: 0
- color: "black"
+ onReadyChanged: {
+ if (ready) {
+ videoSettings.setVideoResolution()
}
+ }
}
- Scene {
- id: sceneController
- camera: cam
- value: ready ? camera.mode == Camera.VideoMode ? settings.videoSceneMode : settings.imageSceneMode : 0
- }
+ Connections {
+ target: settings
- ColorTone {
- id: colorToneController
- camera: cam
- value: ready ? camera.mode == Camera.VideoMode ? settings.videoColorFilter : settings.imageColorFilter : 0
- }
+ onImageAspectRatioChanged: {
+ imageSettings.setImageResolution()
+ }
+
+ onImageResolutionChanged: {
+ imageSettings.setImageResolution()
+ }
- WhiteBalance {
- id: whiteBalanceController
- camera: cam
- value: ready ? camera.mode == Camera.VideoMode ? settings.videoWhiteBalance : settings.imageWhiteBalance : 0
+ onVideoResolutionChanged: {
+ videoSettings.setVideoResolution()
+ }
}
ModeController {
- id: cameraMode
- cam: cam
- dimmer: root.dimmer
+ id: cameraMode
+ cam: cam
+ dimmer: root.dimmer
}
- Connections {
- target: cam
- onModeChanged: {
- if (cam.mode == Camera.VideoMode) {
- replacePage("VideoPage.qml");
- }
- else {
- replacePage("ImagePage.qml");
- }
- }
+ 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
+ }
+
+// Standby {
+// policyLost: pipelineManager.state == "policyLost"
+// TODO:
+// show: !pageStack.currentPage || (pageStack.currentPage.activationData.standbyVisible && pageStack.currentPage.status == PageStatus.Active && pipelineManager.showStandBy)
+// }
}