Don't try to change the resolution while we are changing the device.
[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: front camera night mode
29
30 CameraPage {
31     id: root
32
33     property bool deviceChangeInProgress: false
34
35     CameraTheme {
36         id: cameraTheme
37     }
38
39     VisualItemModel {
40         id: mainModel
41
42         SettingsView {
43             camera: viewfinder.camera
44             width: mainView.width
45             height: mainView.height
46         }
47
48         CameraView {
49             id: viewfinder
50             width: mainView.width
51             height: mainView.height
52         }
53
54         PostCaptureView {
55             camera: viewfinder.camera
56             width: mainView.width
57             height: mainView.height
58         }
59     }
60
61     ListView {
62         id: mainView
63         LayoutMirroring.enabled: false
64         anchors.fill: parent
65         orientation: ListView.Horizontal
66         model: mainModel
67         snapMode: ListView.SnapOneItem
68         highlightRangeMode: ListView.StrictlyEnforceRange
69         boundsBehavior: Flickable.StopAtBounds
70         currentIndex: 1
71         interactive: !currentItem.pressed
72     }
73
74     Component.onCompleted: {
75         platformSettings.init()        
76         root.resetCamera(settings.device, settings.mode)
77     }
78
79     PlatformSettings {
80         id: platformSettings
81     }
82
83     Settings {
84         id: settings
85         onDeviceAboutToChange: {
86             root.deviceChangeInProgress = true
87         }
88
89         onDeviceChanged: {
90             viewfinder.cameraDeviceChanged()
91
92             // Reset pipeline manager error
93             pipelineManager.error = false
94
95             if (root.resetCamera(settings.device, settings.mode)) {
96                 root.deviceChangeInProgress = false
97                 pipelineManager.startCamera()
98             }
99         }
100
101         onImageAspectRatioChanged: {
102             if (!root.deviceChangeInProgress) {
103                 imageSettings.setImageResolution()
104             }
105         }
106
107         onImageResolutionChanged: {
108             if (!root.deviceChangeInProgress) {
109                 imageSettings.setImageResolution()
110             }
111         }
112
113         onVideoResolutionChanged: {
114             if (!root.deviceChangeInProgress) {
115                 videoSettings.setVideoResolution()
116             }
117         }
118     }
119
120     PipelineManager {
121         id: pipelineManager
122         camera: viewfinder.camera
123         currentItem: mainView.currentItem
124     }
125
126     function resetCamera(deviceId, mode) {
127         if (!viewfinder.camera.reset(deviceId, mode)) {
128             showError(qsTr("Failed to set camera device and mode. Please restart the application."))
129             return false
130         }
131
132         if (mode == Camera.ImageMode) {
133             imageSettings.setImageResolution()
134         }
135         else if (mode == Camera.VideoMode) {
136             videoSettings.setVideoResolution()
137         }
138
139         return true
140     }
141
142     function showError(msg) {
143         error.text = msg
144         error.show()
145     }
146
147     property alias dimmer: camDimmer
148     CameraPositionSource {
149         id: positionSource
150         active: settings.useGps
151         // TODO: we cannot bind to cam.running because camera will stop
152         // when the connection dialog pops up and we end up with an infinite loop
153         // active: cam.running && settings.useGps
154         onPositionChanged: geocode.search(position.coordinate.longitude, position.coordinate.latitude)
155     }
156
157     MetaData {
158         id: metaData
159         camera: viewfinder.camera
160         manufacturer: deviceInfo.manufacturer
161         model: deviceInfo.model
162         country: geocode.country
163         city: geocode.city
164         suburb: geocode.suburb
165         longitude: positionSource.longitude
166         longitudeValid: positionSource.longitudeValid && settings.useGps
167         latitude: positionSource.latitude
168         latitudeValid: positionSource.latitudeValid && settings.useGps
169         elevation: positionSource.altitude
170         elevationValid: positionSource.altitudeValid && settings.useGps
171         orientation: orientation.orientation
172         artist: settings.creatorName
173         captureDirection: compass.direction
174         captureDirectionValid: compass.directionValid
175         horizontalError: positionSource.horizontalAccuracy
176         horizontalErrorValid: positionSource.horizontalAccuracyValid && settings.useGps
177         dateTimeEnabled: true
178     }
179
180     CameraOrientation {
181         id: orientation
182         active: viewfinder.camera.running || (mainView.currentIndex == 2 && Qt.application.active)
183     }
184
185     CameraCompass {
186         id: compass
187         active: viewfinder.camera.running
188     }
189
190     ReverseGeocode {
191         id: geocode
192         active: viewfinder.camera.running && settings.useGps && settings.useGeotags
193     }
194
195     DeviceInfo {
196         id: deviceInfo
197     }
198
199     FSMonitor {
200         id: fileSystem
201     }
202
203     CameraInfoBanner {
204         id: error
205     }
206
207     FileNaming {
208         id: fileNaming
209         imageSuffix: viewfinder.camera.imageSuffix
210         videoSuffix: viewfinder.camera.videoSuffix
211         imagePath: platformSettings.imagePath
212         videoPath: platformSettings.videoPath
213         temporaryVideoPath: platformSettings.temporaryVideoPath
214     }
215
216     MountProtector {
217         id: mountProtector
218     }
219
220     TrackerStore {
221         id: trackerStore
222         active: viewfinder.camera.running
223         manufacturer: deviceInfo.manufacturer
224         model: deviceInfo.model
225     }
226
227     ImageSettings {
228         id: imageSettings
229         camera: viewfinder.camera
230
231         function setImageResolution() {
232             if (!imageSettings.setResolution(settings.imageAspectRatio, settings.imageResolution)) {
233                 showError(qsTr("Failed to set required resolution"))
234             }
235         }
236     }
237
238     VideoSettings {
239         id: videoSettings
240         camera: viewfinder.camera
241
242         function setVideoResolution() {
243             if (!videoSettings.setResolution(settings.videoAspectRatio, settings.videoResolution)) {
244                 showError(qsTr("Failed to set required resolution"))
245             }
246         }
247     }
248
249     ModeController {
250         id: cameraMode
251         cam: viewfinder.camera
252         dimmer: root.dimmer
253     }
254
255     Rectangle {
256         property bool dimmed: false
257         id: camDimmer
258         z: 1
259         anchors.fill: parent
260         opacity: dimmed ? 1.0 : 0.0
261         color: "black"
262         Behavior on opacity {
263             PropertyAnimation { duration: 150 }
264         }
265     }
266
267     DeviceKeys {
268         id: keys
269         active: Qt.application.active && pipelineManager.scaleAcquired
270         repeat: !settings.zoomAsShutter
271     }
272
273     Standby {
274         policyLost: pipelineManager.state == "policyLost"
275         show: !Qt.application.active || pipelineManager.showStandBy ||
276             (mainView.currentIndex == 1 && !viewfinder.camera.running)
277     }
278 }