95cba6b0ab1acdd818a6cdee3d0ed8ffd2150bcc
[harmattan/cameraplus] / qml / MainPage.qml
1 // -*- qml -*-
2
3 /*!
4  * This file is part of CameraPlus.
5  *
6  * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 import QtQuick 2.0
24 import QtCamera 1.0
25 import CameraPlus 1.0
26
27 // TODO: flash not ready (battery low or flash not ready message)
28 // TODO: Sounds
29 // TODO: N950 conf
30
31 CameraPage {
32     id: root
33
34     property bool deviceChangeInProgress: false
35     property bool inCaptureMode: mainView.currentIndex == 1
36     property Item dimmer: camDimmer
37
38     CameraTheme {
39         id: cameraTheme
40     }
41
42     VisualItemModel {
43         id: mainModel
44
45         Loader {
46             id: settingsLoader
47             width: mainView.width
48             height: mainView.height
49
50             property bool pressed: false
51             property bool inhibitDim: false
52             property int policyMode: settings.mode == Camera.VideoMode ? CameraResources.Video : CameraResources.Image
53             opacity: item ? 1.0 : 0
54
55             Behavior on opacity {
56                 NumberAnimation {duration: 200}
57             }
58         }
59
60         CameraView {
61             id: viewfinder
62             width: mainView.width
63             height: mainView.height
64         }
65
66         Loader {
67             id: postCaptureLoader
68             property bool pressed: item ? item.pressed : false
69             property bool inhibitDim: item ? item.inhibitDim : false
70             property int policyMode: item ? item.policyMode : settings.mode == Camera.VideoMode ? CameraResources.Video : CameraResources.Image
71
72             width: mainView.width
73             height: mainView.height
74             opacity: item ? 1.0 : 0
75
76             Behavior on opacity {
77                 NumberAnimation {duration: 200}
78             }
79         }
80     }
81
82     ListView {
83         id: mainView
84         LayoutMirroring.enabled: false
85         anchors.fill: parent
86         orientation: ListView.Horizontal
87         model: mainModel
88         snapMode: ListView.SnapOneItem
89         highlightRangeMode: ListView.StrictlyEnforceRange
90         boundsBehavior: Flickable.StopAtBounds
91         currentIndex: 1
92         interactive: !currentItem.pressed
93         onContentXChanged: {
94             if (contentX == 0) {
95                 settingsLoader.source = Qt.resolvedUrl("SettingsView.qml")
96             } else if (contentX == width) {
97                 settingsLoader.source = ""
98                 postCaptureLoader.source = ""
99             } else if (contentX == width * 2) {
100                 postCaptureLoader.source = Qt.resolvedUrl("PostCaptureView.qml")
101             }
102         }
103     }
104
105     Component.onCompleted: {
106         platformSettings.init()        
107         root.resetCamera(settings.device, settings.mode)
108     }
109
110     PlatformSettings {
111         id: platformSettings
112     }
113
114     Settings {
115         id: settings
116         onDeviceAboutToChange: {
117             root.deviceChangeInProgress = true
118         }
119
120         onDeviceChanged: {
121             viewfinder.cameraDeviceChanged()
122
123             // Reset pipeline manager error
124             pipelineManager.error = false
125
126             if (root.resetCamera(settings.device, settings.mode)) {
127                 root.deviceChangeInProgress = false
128                 pipelineManager.startCamera()
129             }
130         }
131
132         onImageAspectRatioChanged: {
133             if (!root.deviceChangeInProgress) {
134                 imageSettings.setImageResolution()
135             }
136         }
137
138         onImageResolutionChanged: {
139             if (!root.deviceChangeInProgress) {
140                 imageSettings.setImageResolution()
141             }
142         }
143
144         onVideoResolutionChanged: {
145             if (!root.deviceChangeInProgress) {
146                 videoSettings.setVideoResolution()
147             }
148         }
149
150         onVideoAspectRatioChanged: {
151             if (!root.deviceChangeInProgress) {
152                 videoSettings.setVideoResolution()
153             }
154         }
155     }
156
157     PipelineManager {
158         id: pipelineManager
159         camera: viewfinder.camera
160         currentItem: mainView.currentItem
161     }
162
163     function resetCamera(deviceId, mode) {
164         if (!viewfinder.camera.reset(deviceId, mode)) {
165             showError(qsTr("Failed to set camera device and mode. Please restart the application."))
166             return false
167         }
168
169         if (mode == Camera.ImageMode) {
170             imageSettings.setImageResolution()
171         }
172         else if (mode == Camera.VideoMode) {
173             videoSettings.setVideoResolution()
174         }
175
176         return true
177     }
178
179     function showError(msg) {
180         error.text = msg
181         error.show()
182     }
183
184     PlatformQuirks {
185         id: platformQuirks
186     }
187
188     DisplayState {
189         id: displayState
190         inhibitDim: mainView.currentItem != null ? mainView.currentItem.inhibitDim : false
191     }
192
193     CameraPositionSource {
194         id: positionSource
195         active: (viewfinder.camera.running || platformQuirks.forceOn) && settings.useGps && displayState.isOn
196         onPositionChanged: geocode.search(position.coordinate.longitude, position.coordinate.latitude)
197     }
198
199     MetaData {
200         id: metaData
201         camera: viewfinder.camera
202         manufacturer: deviceInfo.manufacturer
203         model: deviceInfo.model
204         country: geocode.country
205         city: geocode.city
206         suburb: geocode.suburb
207         longitude: positionSource.longitude
208         longitudeValid: positionSource.longitudeValid && settings.useGps
209         latitude: positionSource.latitude
210         latitudeValid: positionSource.latitudeValid && settings.useGps
211         elevation: positionSource.altitude
212         elevationValid: positionSource.altitudeValid && settings.useGps
213         orientation: orientation.orientation
214         artist: settings.creatorName
215         captureDirection: compass.direction
216         captureDirectionValid: compass.directionValid
217         horizontalError: positionSource.horizontalAccuracy
218         horizontalErrorValid: positionSource.horizontalAccuracyValid && settings.useGps
219         dateTimeEnabled: true
220     }
221
222     CameraOrientation {
223         id: orientation
224         active: viewfinder.camera.running || (mainView.currentIndex == 2 && Qt.application.active)
225     }
226
227     CameraCompass {
228         id: compass
229         active: viewfinder.camera.running
230     }
231
232     ReverseGeocode {
233         id: geocode
234         active: (viewfinder.camera.running || platformQuirks.forceOn) && settings.useGps && settings.useGeotags && displayState.isOn
235     }
236
237     DeviceInfo {
238         id: deviceInfo
239     }
240
241     FSMonitor {
242         id: fileSystem
243     }
244
245     CameraInfoBanner {
246         id: error
247     }
248
249     FileNaming {
250         id: fileNaming
251         imageSuffix: viewfinder.camera.imageSuffix
252         videoSuffix: viewfinder.camera.videoSuffix
253         imagePath: platformSettings.imagePath
254         videoPath: platformSettings.videoPath
255         temporaryVideoPath: platformSettings.temporaryVideoPath
256         settings: settings
257     }
258
259     MountProtector {
260         id: mountProtector
261     }
262
263     TrackerStore {
264         id: trackerStore
265         active: viewfinder.camera.running
266         manufacturer: deviceInfo.manufacturer
267         model: deviceInfo.model
268     }
269
270     ImageSettings {
271         id: imageSettings
272         camera: viewfinder.camera
273
274         function setImageResolution() {
275             if (!imageSettings.setResolution(settings.imageAspectRatio, settings.imageResolution)) {
276                 showError(qsTr("Failed to set required resolution"))
277             }
278         }
279     }
280
281     VideoSettings {
282         id: videoSettings
283         camera: viewfinder.camera
284
285         function setVideoResolution() {
286             if (!videoSettings.setResolution(settings.videoAspectRatio, settings.videoResolution)) {
287                 showError(qsTr("Failed to set required resolution"))
288             }
289         }
290     }
291
292     ModeController {
293         id: cameraMode
294         cam: viewfinder.camera
295         dimmer: root.dimmer
296     }
297
298     Rectangle {
299         property bool dimmed: false
300         id: camDimmer
301         z: 1
302         anchors.fill: parent
303         opacity: dimmed ? 1.0 : 0.0
304         color: "black"
305         Behavior on opacity {
306             PropertyAnimation { duration: 150 }
307         }
308     }
309
310     DeviceKeys {
311         id: keys
312         active: Qt.application.active && pipelineManager.scaleAcquired && root.inCaptureMode && !mainView.moving
313         repeat: !settings.zoomAsShutter
314     }
315
316     Timer {
317         id: proximityTimer
318         running: proximitySensor.close
319         repeat: false
320         interval: 500
321         onTriggered: {
322             if (proximitySensor.close) {
323                 proximitySensor.sensorClosed = true
324             }
325         }
326     }
327
328     CameraProximitySensor {
329         id: proximitySensor
330         property bool sensorClosed: false
331
332         active: Qt.application.active && viewfinder.camera.running && settings.proximityAsShutter && root.inCaptureMode && !mainView.moving
333         onCloseChanged: {
334             if (!close) {
335                 sensorClosed = false
336             }
337         }
338     }
339
340     Standby {
341         policyLost: pipelineManager.state == "policyLost"
342         show: !Qt.application.active || pipelineManager.showStandBy ||
343             (inCaptureMode && !viewfinder.camera.running)
344     }
345 }