Use loaders for post capture and settings views
[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         }
54
55         CameraView {
56             id: viewfinder
57             width: mainView.width
58             height: mainView.height
59         }
60
61         Loader {
62             id: postCaptureLoader
63             property bool pressed: item ? item.pressed : false
64             property bool inhibitDim: item ? item.inhibitDim : false
65             property int policyMode: item ? item.policyMode : settings.mode == Camera.VideoMode ? CameraResources.Video : CameraResources.Image
66
67             width: mainView.width
68             height: mainView.height
69         }
70     }
71
72     ListView {
73         id: mainView
74         LayoutMirroring.enabled: false
75         anchors.fill: parent
76         orientation: ListView.Horizontal
77         model: mainModel
78         snapMode: ListView.SnapOneItem
79         highlightRangeMode: ListView.StrictlyEnforceRange
80         boundsBehavior: Flickable.StopAtBounds
81         currentIndex: 1
82         interactive: !currentItem.pressed
83         onContentXChanged: {
84             if (contentX == 0) {
85                 settingsLoader.source = Qt.resolvedUrl("SettingsView.qml")
86             } else if (contentX == width * 2) {
87                 postCaptureLoader.source = Qt.resolvedUrl("PostCaptureView.qml")
88             }
89         }
90     }
91
92     Component.onCompleted: {
93         platformSettings.init()        
94         root.resetCamera(settings.device, settings.mode)
95     }
96
97     PlatformSettings {
98         id: platformSettings
99     }
100
101     Settings {
102         id: settings
103         onDeviceAboutToChange: {
104             root.deviceChangeInProgress = true
105         }
106
107         onDeviceChanged: {
108             viewfinder.cameraDeviceChanged()
109
110             // Reset pipeline manager error
111             pipelineManager.error = false
112
113             if (root.resetCamera(settings.device, settings.mode)) {
114                 root.deviceChangeInProgress = false
115                 pipelineManager.startCamera()
116             }
117         }
118
119         onImageAspectRatioChanged: {
120             if (!root.deviceChangeInProgress) {
121                 imageSettings.setImageResolution()
122             }
123         }
124
125         onImageResolutionChanged: {
126             if (!root.deviceChangeInProgress) {
127                 imageSettings.setImageResolution()
128             }
129         }
130
131         onVideoResolutionChanged: {
132             if (!root.deviceChangeInProgress) {
133                 videoSettings.setVideoResolution()
134             }
135         }
136
137         onVideoAspectRatioChanged: {
138             if (!root.deviceChangeInProgress) {
139                 videoSettings.setVideoResolution()
140             }
141         }
142     }
143
144     PipelineManager {
145         id: pipelineManager
146         camera: viewfinder.camera
147         currentItem: mainView.currentItem
148     }
149
150     function resetCamera(deviceId, mode) {
151         if (!viewfinder.camera.reset(deviceId, mode)) {
152             showError(qsTr("Failed to set camera device and mode. Please restart the application."))
153             return false
154         }
155
156         if (mode == Camera.ImageMode) {
157             imageSettings.setImageResolution()
158         }
159         else if (mode == Camera.VideoMode) {
160             videoSettings.setVideoResolution()
161         }
162
163         return true
164     }
165
166     function showError(msg) {
167         error.text = msg
168         error.show()
169     }
170
171     PlatformQuirks {
172         id: platformQuirks
173     }
174
175     DisplayState {
176         id: displayState
177         inhibitDim: mainView.currentItem != null ? mainView.currentItem.inhibitDim : false
178     }
179
180     CameraPositionSource {
181         id: positionSource
182         active: (viewfinder.camera.running || platformQuirks.forceOn) && settings.useGps && displayState.isOn
183         onPositionChanged: geocode.search(position.coordinate.longitude, position.coordinate.latitude)
184     }
185
186     MetaData {
187         id: metaData
188         camera: viewfinder.camera
189         manufacturer: deviceInfo.manufacturer
190         model: deviceInfo.model
191         country: geocode.country
192         city: geocode.city
193         suburb: geocode.suburb
194         longitude: positionSource.longitude
195         longitudeValid: positionSource.longitudeValid && settings.useGps
196         latitude: positionSource.latitude
197         latitudeValid: positionSource.latitudeValid && settings.useGps
198         elevation: positionSource.altitude
199         elevationValid: positionSource.altitudeValid && settings.useGps
200         orientation: orientation.orientation
201         artist: settings.creatorName
202         captureDirection: compass.direction
203         captureDirectionValid: compass.directionValid
204         horizontalError: positionSource.horizontalAccuracy
205         horizontalErrorValid: positionSource.horizontalAccuracyValid && settings.useGps
206         dateTimeEnabled: true
207     }
208
209     CameraOrientation {
210         id: orientation
211         active: viewfinder.camera.running || (mainView.currentIndex == 2 && Qt.application.active)
212     }
213
214     CameraCompass {
215         id: compass
216         active: viewfinder.camera.running
217     }
218
219     ReverseGeocode {
220         id: geocode
221         active: (viewfinder.camera.running || platformQuirks.forceOn) && settings.useGps && settings.useGeotags && displayState.isOn
222     }
223
224     DeviceInfo {
225         id: deviceInfo
226     }
227
228     FSMonitor {
229         id: fileSystem
230     }
231
232     CameraInfoBanner {
233         id: error
234     }
235
236     FileNaming {
237         id: fileNaming
238         imageSuffix: viewfinder.camera.imageSuffix
239         videoSuffix: viewfinder.camera.videoSuffix
240         imagePath: platformSettings.imagePath
241         videoPath: platformSettings.videoPath
242         temporaryVideoPath: platformSettings.temporaryVideoPath
243         settings: settings
244     }
245
246     MountProtector {
247         id: mountProtector
248     }
249
250     TrackerStore {
251         id: trackerStore
252         active: viewfinder.camera.running
253         manufacturer: deviceInfo.manufacturer
254         model: deviceInfo.model
255     }
256
257     ImageSettings {
258         id: imageSettings
259         camera: viewfinder.camera
260
261         function setImageResolution() {
262             if (!imageSettings.setResolution(settings.imageAspectRatio, settings.imageResolution)) {
263                 showError(qsTr("Failed to set required resolution"))
264             }
265         }
266     }
267
268     VideoSettings {
269         id: videoSettings
270         camera: viewfinder.camera
271
272         function setVideoResolution() {
273             if (!videoSettings.setResolution(settings.videoAspectRatio, settings.videoResolution)) {
274                 showError(qsTr("Failed to set required resolution"))
275             }
276         }
277     }
278
279     ModeController {
280         id: cameraMode
281         cam: viewfinder.camera
282         dimmer: root.dimmer
283     }
284
285     Rectangle {
286         property bool dimmed: false
287         id: camDimmer
288         z: 1
289         anchors.fill: parent
290         opacity: dimmed ? 1.0 : 0.0
291         color: "black"
292         Behavior on opacity {
293             PropertyAnimation { duration: 150 }
294         }
295     }
296
297     DeviceKeys {
298         id: keys
299         active: Qt.application.active && pipelineManager.scaleAcquired && root.inCaptureMode && !mainView.moving
300         repeat: !settings.zoomAsShutter
301     }
302
303     Timer {
304         id: proximityTimer
305         running: proximitySensor.close
306         repeat: false
307         interval: 500
308         onTriggered: {
309             if (proximitySensor.close) {
310                 proximitySensor.sensorClosed = true
311             }
312         }
313     }
314
315     CameraProximitySensor {
316         id: proximitySensor
317         property bool sensorClosed: false
318
319         active: Qt.application.active && viewfinder.camera.running && settings.proximityAsShutter && root.inCaptureMode && !mainView.moving
320         onCloseChanged: {
321             if (!close) {
322                 sensorClosed = false
323             }
324         }
325     }
326
327     Standby {
328         policyLost: pipelineManager.state == "policyLost"
329         show: !Qt.application.active || pipelineManager.showStandBy ||
330             (inCaptureMode && !viewfinder.camera.running)
331     }
332 }