Merge lp:~fboucault/camera-app/custom_rotation into lp:camera-app
- custom_rotation
- Merge into trunk
Status: | Merged | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Bill Filler | ||||||||||||||||||||||||||||||||
Approved revision: | 573 | ||||||||||||||||||||||||||||||||
Merged at revision: | 571 | ||||||||||||||||||||||||||||||||
Proposed branch: | lp:~fboucault/camera-app/custom_rotation | ||||||||||||||||||||||||||||||||
Merge into: | lp:camera-app | ||||||||||||||||||||||||||||||||
Prerequisite: | lp:~canonical-platform-qa/camera-app/fix1444170-flake8 | ||||||||||||||||||||||||||||||||
Diff against target: |
1040 lines (+478/-365) 10 files modified
CircleButton.qml (+3/-2) OptionButton.qml (+1/-0) OptionsOverlay.qml (+1/-1) PhotoRollHint.qml (+30/-28) Snapshot.qml (+20/-5) ViewFinderOverlay.qml (+287/-279) ViewFinderView.qml (+1/-1) camera-app.desktop.in.in (+1/-0) camera-app.qml (+126/-43) tests/autopilot/camera_app/tests/test_flash.py (+8/-6) |
||||||||||||||||||||||||||||||||
To merge this branch: | bzr merge lp:~fboucault/camera-app/custom_rotation | ||||||||||||||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ubuntu Phablet Team | Pending | ||
Review via email: mp+263778@code.launchpad.net |
This proposal supersedes a proposal from 2015-06-29.
Commit message
Set desktop file flags informing Unity that the camera app is doing its own content rotation when the device rotates.
Manually rotate/position depending on device orientation:
- photo roll
- bottom edge indicators and content
- first photo roll hint
- snapshot animation
- countdown timer
Description of the change
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:570
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 571. By Florian Boucault
-
Merged lp:~canonical-platform-qa/camera-app/fix1444170-flake8
- 572. By Florian Boucault
-
More robust camera_
app.tests. test_flash. TestCameraFlash .test_flash_ hdr_mutually_ exclusive
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:572
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 573. By Florian Boucault
-
More appropriate bottom edge input area.
Bill Filler (bfiller) wrote : | # |
tested, works on arale and krillin
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:573
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'CircleButton.qml' | |||
2 | --- CircleButton.qml 2014-12-05 18:57:32 +0000 | |||
3 | +++ CircleButton.qml 2015-07-03 18:21:53 +0000 | |||
4 | @@ -25,6 +25,7 @@ | |||
5 | 25 | property url iconSource | 25 | property url iconSource |
6 | 26 | property bool on: true | 26 | property bool on: true |
7 | 27 | property string label: "" | 27 | property string label: "" |
8 | 28 | property bool automaticOrientation: true | ||
9 | 28 | 29 | ||
10 | 29 | width: units.gu(5) | 30 | width: units.gu(5) |
11 | 30 | height: width | 31 | height: width |
12 | @@ -49,7 +50,7 @@ | |||
13 | 49 | color: "white" | 50 | color: "white" |
14 | 50 | opacity: button.on ? (button.enabled ? 1.0 : 0.3): 0.5 | 51 | opacity: button.on ? (button.enabled ? 1.0 : 0.3): 0.5 |
15 | 51 | visible: label === "" | 52 | visible: label === "" |
17 | 52 | rotation: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation) | 53 | rotation: automaticOrientation ? Screen.angleBetween(Screen.primaryOrientation, Screen.orientation) : 0 |
18 | 53 | Behavior on rotation { | 54 | Behavior on rotation { |
19 | 54 | RotationAnimator { | 55 | RotationAnimator { |
20 | 55 | duration: UbuntuAnimation.BriskDuration | 56 | duration: UbuntuAnimation.BriskDuration |
21 | @@ -69,7 +70,7 @@ | |||
22 | 69 | text: label | 70 | text: label |
23 | 70 | opacity: button.on ? (button.enabled ? 1.0 : 0.3): 0.5 | 71 | opacity: button.on ? (button.enabled ? 1.0 : 0.3): 0.5 |
24 | 71 | visible: label !== "" | 72 | visible: label !== "" |
26 | 72 | rotation: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation) | 73 | rotation: automaticOrientation ? Screen.angleBetween(Screen.primaryOrientation, Screen.orientation) : 0 |
27 | 73 | Behavior on rotation { | 74 | Behavior on rotation { |
28 | 74 | RotationAnimator { | 75 | RotationAnimator { |
29 | 75 | duration: UbuntuAnimation.BriskDuration | 76 | duration: UbuntuAnimation.BriskDuration |
30 | 76 | 77 | ||
31 | === modified file 'OptionButton.qml' | |||
32 | --- OptionButton.qml 2015-01-27 11:32:45 +0000 | |||
33 | +++ OptionButton.qml 2015-07-03 18:21:53 +0000 | |||
34 | @@ -29,4 +29,5 @@ | |||
35 | 29 | enabled: model.available | 29 | enabled: model.available |
36 | 30 | label: model.label | 30 | label: model.label |
37 | 31 | visible: model.visible | 31 | visible: model.visible |
38 | 32 | automaticOrientation: false | ||
39 | 32 | } | 33 | } |
40 | 33 | 34 | ||
41 | === modified file 'OptionsOverlay.qml' | |||
42 | --- OptionsOverlay.qml 2015-01-27 15:22:59 +0000 | |||
43 | +++ OptionsOverlay.qml 2015-07-03 18:21:53 +0000 | |||
44 | @@ -37,7 +37,7 @@ | |||
45 | 37 | 37 | ||
46 | 38 | columns: 3 | 38 | columns: 3 |
47 | 39 | columnSpacing: units.gu(9.5) | 39 | columnSpacing: units.gu(9.5) |
49 | 40 | rowSpacing: units.gu(4) | 40 | rowSpacing: units.gu(3) |
50 | 41 | 41 | ||
51 | 42 | Repeater { | 42 | Repeater { |
52 | 43 | model: optionsOverlay.options | 43 | model: optionsOverlay.options |
53 | 44 | 44 | ||
54 | === modified file 'PhotoRollHint.qml' | |||
55 | --- PhotoRollHint.qml 2014-11-05 10:17:23 +0000 | |||
56 | +++ PhotoRollHint.qml 2015-07-03 18:21:53 +0000 | |||
57 | @@ -40,33 +40,35 @@ | |||
58 | 40 | property alias photoRollHintNecessary: photoRollHint.necessary | 40 | property alias photoRollHintNecessary: photoRollHint.necessary |
59 | 41 | } | 41 | } |
60 | 42 | 42 | ||
89 | 43 | Image { | 43 | OrientationHelper { |
90 | 44 | id: hintPictogram | 44 | Image { |
91 | 45 | anchors { | 45 | id: hintPictogram |
92 | 46 | horizontalCenter: parent.horizontalCenter | 46 | anchors { |
93 | 47 | horizontalCenterOffset: units.gu(4) | 47 | horizontalCenter: parent.horizontalCenter |
94 | 48 | verticalCenter: parent.verticalCenter | 48 | horizontalCenterOffset: units.gu(4) |
95 | 49 | verticalCenterOffset: -units.gu(1) | 49 | verticalCenter: parent.verticalCenter |
96 | 50 | } | 50 | verticalCenterOffset: -units.gu(1) |
97 | 51 | 51 | } | |
98 | 52 | asynchronous: true | 52 | |
99 | 53 | cache: false | 53 | asynchronous: true |
100 | 54 | source: photoRollHint.enabled ? "assets/camera_swipe.png" : "" | 54 | cache: false |
101 | 55 | } | 55 | source: photoRollHint.enabled ? "assets/camera_swipe.png" : "" |
102 | 56 | 56 | } | |
103 | 57 | Label { | 57 | |
104 | 58 | id: hintLabel | 58 | Label { |
105 | 59 | 59 | id: hintLabel | |
106 | 60 | anchors { | 60 | |
107 | 61 | top: hintPictogram.bottom | 61 | anchors { |
108 | 62 | topMargin: units.gu(5) | 62 | top: hintPictogram.bottom |
109 | 63 | horizontalCenter: parent.horizontalCenter | 63 | topMargin: units.gu(5) |
110 | 64 | } | 64 | horizontalCenter: parent.horizontalCenter |
111 | 65 | width: parent.width - 2 * units.gu(2) | 65 | } |
112 | 66 | horizontalAlignment: Text.AlignHCenter | 66 | width: parent.width - 2 * units.gu(2) |
113 | 67 | wrapMode: Text.Wrap | 67 | horizontalAlignment: Text.AlignHCenter |
114 | 68 | text: i18n.tr("Swipe left for photo roll") | 68 | wrapMode: Text.Wrap |
115 | 69 | fontSize: "x-large" | 69 | text: i18n.tr("Swipe left for photo roll") |
116 | 70 | color: "#ebebeb" | 70 | fontSize: "x-large" |
117 | 71 | color: "#ebebeb" | ||
118 | 72 | } | ||
119 | 71 | } | 73 | } |
120 | 72 | } | 74 | } |
121 | 73 | 75 | ||
122 | === modified file 'Snapshot.qml' | |||
123 | --- Snapshot.qml 2014-10-09 19:07:35 +0000 | |||
124 | +++ Snapshot.qml 2015-07-03 18:21:53 +0000 | |||
125 | @@ -15,6 +15,7 @@ | |||
126 | 15 | */ | 15 | */ |
127 | 16 | 16 | ||
128 | 17 | import QtQuick 2.2 | 17 | import QtQuick 2.2 |
129 | 18 | import QtQuick.Window 2.0 | ||
130 | 18 | import Ubuntu.Components 1.0 | 19 | import Ubuntu.Components 1.0 |
131 | 19 | 20 | ||
132 | 20 | Item { | 21 | Item { |
133 | @@ -34,11 +35,8 @@ | |||
134 | 34 | 35 | ||
135 | 35 | Item { | 36 | Item { |
136 | 36 | id: container | 37 | id: container |
137 | 37 | anchors { | ||
138 | 38 | top: parent.top | ||
139 | 39 | bottom: parent.bottom | ||
140 | 40 | } | ||
141 | 41 | width: parent.width | 38 | width: parent.width |
142 | 39 | height: parent.height | ||
143 | 42 | 40 | ||
144 | 43 | Image { | 41 | Image { |
145 | 44 | id: snapshot | 42 | id: snapshot |
146 | @@ -69,15 +67,32 @@ | |||
147 | 69 | cache: false | 67 | cache: false |
148 | 70 | } | 68 | } |
149 | 71 | } | 69 | } |
150 | 70 | property int orientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation) | ||
151 | 71 | property var angleToOrientation: {0: "PORTRAIT", | ||
152 | 72 | 90: "LANDSCAPE", | ||
153 | 73 | 270: "INVERTED_LANDSCAPE"} | ||
154 | 72 | 74 | ||
155 | 73 | SequentialAnimation { | 75 | SequentialAnimation { |
156 | 74 | id: shoot | 76 | id: shoot |
157 | 75 | 77 | ||
158 | 76 | PropertyAction { target: snapshotRoot; property: "visible"; value: true } | 78 | PropertyAction { target: snapshotRoot; property: "visible"; value: true } |
159 | 77 | PauseAnimation { duration: 150 } | 79 | PauseAnimation { duration: 150 } |
161 | 78 | XAnimator { target: container; to: container.width + shadow.width; duration: UbuntuAnimation.BriskDuration; easing: UbuntuAnimation.StandardEasing} | 80 | XAnimator { |
162 | 81 | target: container | ||
163 | 82 | to: angleToOrientation[orientationAngle] == "PORTRAIT" ? container.width + shadow.width : 0 | ||
164 | 83 | duration: UbuntuAnimation.BriskDuration | ||
165 | 84 | easing: UbuntuAnimation.StandardEasing | ||
166 | 85 | } | ||
167 | 86 | YAnimator { | ||
168 | 87 | target: container | ||
169 | 88 | to: angleToOrientation[orientationAngle] == "LANDSCAPE" ? container.height + shadow.width : | ||
170 | 89 | angleToOrientation[orientationAngle] == "INVERTED_LANDSCAPE" ? -(container.height + shadow.width) : 0 | ||
171 | 90 | duration: UbuntuAnimation.BriskDuration | ||
172 | 91 | easing: UbuntuAnimation.StandardEasing | ||
173 | 92 | } | ||
174 | 79 | PropertyAction { target: snapshot; property: "source"; value: ""} | 93 | PropertyAction { target: snapshot; property: "source"; value: ""} |
175 | 80 | PropertyAction { target: snapshotRoot; property: "visible"; value: false } | 94 | PropertyAction { target: snapshotRoot; property: "visible"; value: false } |
176 | 81 | PropertyAction { target: container; property: "x"; value: 0 } | 95 | PropertyAction { target: container; property: "x"; value: 0 } |
177 | 96 | PropertyAction { target: container; property: "y"; value: 0 } | ||
178 | 82 | } | 97 | } |
179 | 83 | } | 98 | } |
180 | 84 | 99 | ||
181 | === modified file 'ViewFinderOverlay.qml' | |||
182 | --- ViewFinderOverlay.qml 2015-03-13 00:41:54 +0000 | |||
183 | +++ ViewFinderOverlay.qml 2015-07-03 18:21:53 +0000 | |||
184 | @@ -159,269 +159,290 @@ | |||
185 | 159 | onClicked: optionsOverlayClose() | 159 | onClicked: optionsOverlayClose() |
186 | 160 | } | 160 | } |
187 | 161 | 161 | ||
445 | 162 | Panel { | 162 | OrientationHelper { |
446 | 163 | id: bottomEdge | 163 | id: bottomEdgeOrientation |
447 | 164 | anchors { | 164 | transitionEnabled: bottomEdge.opened |
448 | 165 | right: parent.right | 165 | |
449 | 166 | left: parent.left | 166 | Panel { |
450 | 167 | bottom: parent.bottom | 167 | id: bottomEdge |
194 | 168 | } | ||
195 | 169 | height: optionsOverlayLoader.height | ||
196 | 170 | onOpenedChanged: optionsOverlayLoader.item.closeValueSelector() | ||
197 | 171 | enabled: camera.videoRecorder.recorderState == CameraRecorder.StoppedState | ||
198 | 172 | opacity: enabled ? 1.0 : 0.3 | ||
199 | 173 | |||
200 | 174 | Item { | ||
201 | 175 | /* Use the 'trigger' feature of Panel so that tapping on the Panel | ||
202 | 176 | has the same effect as tapping outside of it (bottomEdgeClose) */ | ||
203 | 177 | id: clickReceiver | ||
204 | 178 | anchors.fill: parent | ||
205 | 179 | function trigger() { | ||
206 | 180 | optionsOverlayClose(); | ||
207 | 181 | } | ||
208 | 182 | } | ||
209 | 183 | |||
210 | 184 | property real progress: (bottomEdge.height - bottomEdge.position) / bottomEdge.height | ||
211 | 185 | property list<ListModel> options: [ | ||
212 | 186 | ListModel { | ||
213 | 187 | id: gpsOptionsModel | ||
214 | 188 | |||
215 | 189 | property string settingsProperty: "gpsEnabled" | ||
216 | 190 | property string icon: "location" | ||
217 | 191 | property string label: "" | ||
218 | 192 | property bool isToggle: true | ||
219 | 193 | property int selectedIndex: bottomEdge.indexForValue(gpsOptionsModel, settings.gpsEnabled) | ||
220 | 194 | property bool available: true | ||
221 | 195 | property bool visible: true | ||
222 | 196 | property bool showInIndicators: true | ||
223 | 197 | |||
224 | 198 | ListElement { | ||
225 | 199 | icon: "" | ||
226 | 200 | label: QT_TR_NOOP("On") | ||
227 | 201 | value: true | ||
228 | 202 | } | ||
229 | 203 | ListElement { | ||
230 | 204 | icon: "" | ||
231 | 205 | label: QT_TR_NOOP("Off") | ||
232 | 206 | value: false | ||
233 | 207 | } | ||
234 | 208 | }, | ||
235 | 209 | ListModel { | ||
236 | 210 | id: flashOptionsModel | ||
237 | 211 | |||
238 | 212 | property string settingsProperty: "flashMode" | ||
239 | 213 | property string icon: "" | ||
240 | 214 | property string label: "" | ||
241 | 215 | property bool isToggle: false | ||
242 | 216 | property int selectedIndex: bottomEdge.indexForValue(flashOptionsModel, settings.flashMode) | ||
243 | 217 | property bool available: camera.advanced.hasFlash | ||
244 | 218 | property bool visible: camera.captureMode == Camera.CaptureStillImage | ||
245 | 219 | property bool showInIndicators: true | ||
246 | 220 | |||
247 | 221 | ListElement { | ||
248 | 222 | icon: "flash-on" | ||
249 | 223 | label: QT_TR_NOOP("On") | ||
250 | 224 | value: Camera.FlashOn | ||
251 | 225 | } | ||
252 | 226 | ListElement { | ||
253 | 227 | icon: "flash-auto" | ||
254 | 228 | label: QT_TR_NOOP("Auto") | ||
255 | 229 | value: Camera.FlashAuto | ||
256 | 230 | } | ||
257 | 231 | ListElement { | ||
258 | 232 | icon: "flash-off" | ||
259 | 233 | label: QT_TR_NOOP("Off") | ||
260 | 234 | value: Camera.FlashOff | ||
261 | 235 | } | ||
262 | 236 | }, | ||
263 | 237 | ListModel { | ||
264 | 238 | id: videoFlashOptionsModel | ||
265 | 239 | |||
266 | 240 | property string settingsProperty: "videoFlashMode" | ||
267 | 241 | property string icon: "" | ||
268 | 242 | property string label: "" | ||
269 | 243 | property bool isToggle: false | ||
270 | 244 | property int selectedIndex: bottomEdge.indexForValue(videoFlashOptionsModel, settings.videoFlashMode) | ||
271 | 245 | property bool available: camera.advanced.hasFlash | ||
272 | 246 | property bool visible: camera.captureMode == Camera.CaptureVideo | ||
273 | 247 | property bool showInIndicators: true | ||
274 | 248 | |||
275 | 249 | ListElement { | ||
276 | 250 | icon: "torch-on" | ||
277 | 251 | label: QT_TR_NOOP("On") | ||
278 | 252 | value: Camera.FlashVideoLight | ||
279 | 253 | } | ||
280 | 254 | ListElement { | ||
281 | 255 | icon: "torch-off" | ||
282 | 256 | label: QT_TR_NOOP("Off") | ||
283 | 257 | value: Camera.FlashOff | ||
284 | 258 | } | ||
285 | 259 | }, | ||
286 | 260 | ListModel { | ||
287 | 261 | id: hdrOptionsModel | ||
288 | 262 | |||
289 | 263 | property string settingsProperty: "hdrEnabled" | ||
290 | 264 | property string icon: "" | ||
291 | 265 | property string label: i18n.tr("HDR") | ||
292 | 266 | property bool isToggle: true | ||
293 | 267 | property int selectedIndex: bottomEdge.indexForValue(hdrOptionsModel, settings.hdrEnabled) | ||
294 | 268 | property bool available: camera.advanced.hasHdr | ||
295 | 269 | property bool visible: true | ||
296 | 270 | property bool showInIndicators: true | ||
297 | 271 | |||
298 | 272 | ListElement { | ||
299 | 273 | icon: "" | ||
300 | 274 | label: QT_TR_NOOP("On") | ||
301 | 275 | value: true | ||
302 | 276 | } | ||
303 | 277 | ListElement { | ||
304 | 278 | icon: "" | ||
305 | 279 | label: QT_TR_NOOP("Off") | ||
306 | 280 | value: false | ||
307 | 281 | } | ||
308 | 282 | }, | ||
309 | 283 | ListModel { | ||
310 | 284 | id: selfTimerOptionsModel | ||
311 | 285 | |||
312 | 286 | property string settingsProperty: "selfTimerDelay" | ||
313 | 287 | property string icon: "" | ||
314 | 288 | property string iconSource: "assets/self_timer.svg" | ||
315 | 289 | property string label: "" | ||
316 | 290 | property bool isToggle: true | ||
317 | 291 | property int selectedIndex: bottomEdge.indexForValue(selfTimerOptionsModel, settings.selfTimerDelay) | ||
318 | 292 | property bool available: true | ||
319 | 293 | property bool visible: true | ||
320 | 294 | property bool showInIndicators: true | ||
321 | 295 | |||
322 | 296 | ListElement { | ||
323 | 297 | icon: "" | ||
324 | 298 | label: QT_TR_NOOP("Off") | ||
325 | 299 | value: 0 | ||
326 | 300 | } | ||
327 | 301 | ListElement { | ||
328 | 302 | icon: "" | ||
329 | 303 | label: QT_TR_NOOP("5 seconds") | ||
330 | 304 | value: 5 | ||
331 | 305 | } | ||
332 | 306 | ListElement { | ||
333 | 307 | icon: "" | ||
334 | 308 | label: QT_TR_NOOP("15 seconds") | ||
335 | 309 | value: 15 | ||
336 | 310 | } | ||
337 | 311 | }, | ||
338 | 312 | ListModel { | ||
339 | 313 | id: encodingQualityOptionsModel | ||
340 | 314 | |||
341 | 315 | property string settingsProperty: "encodingQuality" | ||
342 | 316 | property string icon: "stock_image" | ||
343 | 317 | property string label: "" | ||
344 | 318 | property bool isToggle: false | ||
345 | 319 | property int selectedIndex: bottomEdge.indexForValue(encodingQualityOptionsModel, settings.encodingQuality) | ||
346 | 320 | property bool available: true | ||
347 | 321 | property bool visible: camera.captureMode == Camera.CaptureStillImage | ||
348 | 322 | property bool showInIndicators: false | ||
349 | 323 | |||
350 | 324 | ListElement { | ||
351 | 325 | label: QT_TR_NOOP("Fine Quality") | ||
352 | 326 | value: 4 // QMultimedia.VeryHighQuality | ||
353 | 327 | } | ||
354 | 328 | ListElement { | ||
355 | 329 | label: QT_TR_NOOP("Normal Quality") | ||
356 | 330 | value: 2 // QMultimedia.NormalQuality | ||
357 | 331 | } | ||
358 | 332 | ListElement { | ||
359 | 333 | label: QT_TR_NOOP("Basic Quality") | ||
360 | 334 | value: 1 // QMultimedia.LowQuality | ||
361 | 335 | } | ||
362 | 336 | }, | ||
363 | 337 | ListModel { | ||
364 | 338 | id: gridOptionsModel | ||
365 | 339 | |||
366 | 340 | property string settingsProperty: "gridEnabled" | ||
367 | 341 | property string icon: "" | ||
368 | 342 | property string iconSource: "assets/grid_lines.svg" | ||
369 | 343 | property string label: "" | ||
370 | 344 | property bool isToggle: true | ||
371 | 345 | property int selectedIndex: bottomEdge.indexForValue(gridOptionsModel, settings.gridEnabled) | ||
372 | 346 | property bool available: true | ||
373 | 347 | property bool visible: true | ||
374 | 348 | |||
375 | 349 | ListElement { | ||
376 | 350 | icon: "" | ||
377 | 351 | label: QT_TR_NOOP("On") | ||
378 | 352 | value: true | ||
379 | 353 | } | ||
380 | 354 | ListElement { | ||
381 | 355 | icon: "" | ||
382 | 356 | label: QT_TR_NOOP("Off") | ||
383 | 357 | value: false | ||
384 | 358 | } | ||
385 | 359 | }, | ||
386 | 360 | ListModel { | ||
387 | 361 | id: removableStorageOptionsModel | ||
388 | 362 | |||
389 | 363 | property string settingsProperty: "preferRemovableStorage" | ||
390 | 364 | property string icon: "" | ||
391 | 365 | property string label: i18n.tr("SD") | ||
392 | 366 | property bool isToggle: true | ||
393 | 367 | property int selectedIndex: bottomEdge.indexForValue(removableStorageOptionsModel, settings.preferRemovableStorage) | ||
394 | 368 | property bool available: application.removableStoragePresent | ||
395 | 369 | property bool visible: available | ||
396 | 370 | |||
397 | 371 | ListElement { | ||
398 | 372 | icon: "" | ||
399 | 373 | label: QT_TR_NOOP("Save to SD Card") | ||
400 | 374 | value: true | ||
401 | 375 | } | ||
402 | 376 | ListElement { | ||
403 | 377 | icon: "" | ||
404 | 378 | label: QT_TR_NOOP("Save internally") | ||
405 | 379 | value: false | ||
406 | 380 | } | ||
407 | 381 | }, | ||
408 | 382 | ListModel { | ||
409 | 383 | id: videoResolutionOptionsModel | ||
410 | 384 | |||
411 | 385 | property string settingsProperty: "videoResolution" | ||
412 | 386 | property string icon: "" | ||
413 | 387 | property string label: "HD" | ||
414 | 388 | property bool isToggle: false | ||
415 | 389 | property int selectedIndex: bottomEdge.indexForValue(videoResolutionOptionsModel, settings.videoResolution) | ||
416 | 390 | property bool available: true | ||
417 | 391 | property bool visible: camera.captureMode == Camera.CaptureVideo | ||
418 | 392 | property bool showInIndicators: false | ||
419 | 393 | } | ||
420 | 394 | ] | ||
421 | 395 | |||
422 | 396 | /* FIXME: application.removableStoragePresent is not updated dynamically. | ||
423 | 397 | Workaround that by reading it when the bottom edge is opened/closed. | ||
424 | 398 | */ | ||
425 | 399 | Connections { | ||
426 | 400 | target: bottomEdge | ||
427 | 401 | onOpenedChanged: removableStorageOptionsModel.available = application.removableStoragePresent | ||
428 | 402 | } | ||
429 | 403 | |||
430 | 404 | function indexForValue(model, value) { | ||
431 | 405 | var i; | ||
432 | 406 | var element; | ||
433 | 407 | for (i=0; i<model.count; i++) { | ||
434 | 408 | element = model.get(i); | ||
435 | 409 | if (element.value === value) { | ||
436 | 410 | return i; | ||
437 | 411 | } | ||
438 | 412 | } | ||
439 | 413 | |||
440 | 414 | return -1; | ||
441 | 415 | } | ||
442 | 416 | |||
443 | 417 | BottomEdgeIndicators { | ||
444 | 418 | options: bottomEdge.options | ||
451 | 419 | anchors { | 168 | anchors { |
457 | 420 | horizontalCenter: parent.horizontalCenter | 169 | right: parent.right |
458 | 421 | bottom: parent.top | 170 | left: parent.left |
459 | 422 | } | 171 | bottom: parent.bottom |
460 | 423 | opacity: bottomEdge.pressed || bottomEdge.opened ? 0.0 : 1.0 | 172 | } |
461 | 424 | Behavior on opacity { UbuntuNumberAnimation {} } | 173 | height: optionsOverlayLoader.height |
462 | 174 | onOpenedChanged: optionsOverlayLoader.item.closeValueSelector() | ||
463 | 175 | enabled: camera.videoRecorder.recorderState == CameraRecorder.StoppedState | ||
464 | 176 | opacity: enabled ? 1.0 : 0.3 | ||
465 | 177 | |||
466 | 178 | Item { | ||
467 | 179 | /* Use the 'trigger' feature of Panel so that tapping on the Panel | ||
468 | 180 | has the same effect as tapping outside of it (bottomEdgeClose) */ | ||
469 | 181 | id: clickReceiver | ||
470 | 182 | anchors.fill: parent | ||
471 | 183 | function trigger() { | ||
472 | 184 | optionsOverlayClose(); | ||
473 | 185 | } | ||
474 | 186 | } | ||
475 | 187 | |||
476 | 188 | property real progress: (bottomEdge.height - bottomEdge.position) / bottomEdge.height | ||
477 | 189 | property list<ListModel> options: [ | ||
478 | 190 | ListModel { | ||
479 | 191 | id: gpsOptionsModel | ||
480 | 192 | |||
481 | 193 | property string settingsProperty: "gpsEnabled" | ||
482 | 194 | property string icon: "location" | ||
483 | 195 | property string label: "" | ||
484 | 196 | property bool isToggle: true | ||
485 | 197 | property int selectedIndex: bottomEdge.indexForValue(gpsOptionsModel, settings.gpsEnabled) | ||
486 | 198 | property bool available: true | ||
487 | 199 | property bool visible: true | ||
488 | 200 | property bool showInIndicators: true | ||
489 | 201 | |||
490 | 202 | ListElement { | ||
491 | 203 | icon: "" | ||
492 | 204 | label: QT_TR_NOOP("On") | ||
493 | 205 | value: true | ||
494 | 206 | } | ||
495 | 207 | ListElement { | ||
496 | 208 | icon: "" | ||
497 | 209 | label: QT_TR_NOOP("Off") | ||
498 | 210 | value: false | ||
499 | 211 | } | ||
500 | 212 | }, | ||
501 | 213 | ListModel { | ||
502 | 214 | id: flashOptionsModel | ||
503 | 215 | |||
504 | 216 | property string settingsProperty: "flashMode" | ||
505 | 217 | property string icon: "" | ||
506 | 218 | property string label: "" | ||
507 | 219 | property bool isToggle: false | ||
508 | 220 | property int selectedIndex: bottomEdge.indexForValue(flashOptionsModel, settings.flashMode) | ||
509 | 221 | property bool available: camera.advanced.hasFlash | ||
510 | 222 | property bool visible: camera.captureMode == Camera.CaptureStillImage | ||
511 | 223 | property bool showInIndicators: true | ||
512 | 224 | |||
513 | 225 | ListElement { | ||
514 | 226 | icon: "flash-on" | ||
515 | 227 | label: QT_TR_NOOP("On") | ||
516 | 228 | value: Camera.FlashOn | ||
517 | 229 | } | ||
518 | 230 | ListElement { | ||
519 | 231 | icon: "flash-auto" | ||
520 | 232 | label: QT_TR_NOOP("Auto") | ||
521 | 233 | value: Camera.FlashAuto | ||
522 | 234 | } | ||
523 | 235 | ListElement { | ||
524 | 236 | icon: "flash-off" | ||
525 | 237 | label: QT_TR_NOOP("Off") | ||
526 | 238 | value: Camera.FlashOff | ||
527 | 239 | } | ||
528 | 240 | }, | ||
529 | 241 | ListModel { | ||
530 | 242 | id: videoFlashOptionsModel | ||
531 | 243 | |||
532 | 244 | property string settingsProperty: "videoFlashMode" | ||
533 | 245 | property string icon: "" | ||
534 | 246 | property string label: "" | ||
535 | 247 | property bool isToggle: false | ||
536 | 248 | property int selectedIndex: bottomEdge.indexForValue(videoFlashOptionsModel, settings.videoFlashMode) | ||
537 | 249 | property bool available: camera.advanced.hasFlash | ||
538 | 250 | property bool visible: camera.captureMode == Camera.CaptureVideo | ||
539 | 251 | property bool showInIndicators: true | ||
540 | 252 | |||
541 | 253 | ListElement { | ||
542 | 254 | icon: "torch-on" | ||
543 | 255 | label: QT_TR_NOOP("On") | ||
544 | 256 | value: Camera.FlashVideoLight | ||
545 | 257 | } | ||
546 | 258 | ListElement { | ||
547 | 259 | icon: "torch-off" | ||
548 | 260 | label: QT_TR_NOOP("Off") | ||
549 | 261 | value: Camera.FlashOff | ||
550 | 262 | } | ||
551 | 263 | }, | ||
552 | 264 | ListModel { | ||
553 | 265 | id: hdrOptionsModel | ||
554 | 266 | |||
555 | 267 | property string settingsProperty: "hdrEnabled" | ||
556 | 268 | property string icon: "" | ||
557 | 269 | property string label: i18n.tr("HDR") | ||
558 | 270 | property bool isToggle: true | ||
559 | 271 | property int selectedIndex: bottomEdge.indexForValue(hdrOptionsModel, settings.hdrEnabled) | ||
560 | 272 | property bool available: camera.advanced.hasHdr | ||
561 | 273 | property bool visible: true | ||
562 | 274 | property bool showInIndicators: true | ||
563 | 275 | |||
564 | 276 | ListElement { | ||
565 | 277 | icon: "" | ||
566 | 278 | label: QT_TR_NOOP("On") | ||
567 | 279 | value: true | ||
568 | 280 | } | ||
569 | 281 | ListElement { | ||
570 | 282 | icon: "" | ||
571 | 283 | label: QT_TR_NOOP("Off") | ||
572 | 284 | value: false | ||
573 | 285 | } | ||
574 | 286 | }, | ||
575 | 287 | ListModel { | ||
576 | 288 | id: selfTimerOptionsModel | ||
577 | 289 | |||
578 | 290 | property string settingsProperty: "selfTimerDelay" | ||
579 | 291 | property string icon: "" | ||
580 | 292 | property string iconSource: "assets/self_timer.svg" | ||
581 | 293 | property string label: "" | ||
582 | 294 | property bool isToggle: true | ||
583 | 295 | property int selectedIndex: bottomEdge.indexForValue(selfTimerOptionsModel, settings.selfTimerDelay) | ||
584 | 296 | property bool available: true | ||
585 | 297 | property bool visible: true | ||
586 | 298 | property bool showInIndicators: true | ||
587 | 299 | |||
588 | 300 | ListElement { | ||
589 | 301 | icon: "" | ||
590 | 302 | label: QT_TR_NOOP("Off") | ||
591 | 303 | value: 0 | ||
592 | 304 | } | ||
593 | 305 | ListElement { | ||
594 | 306 | icon: "" | ||
595 | 307 | label: QT_TR_NOOP("5 seconds") | ||
596 | 308 | value: 5 | ||
597 | 309 | } | ||
598 | 310 | ListElement { | ||
599 | 311 | icon: "" | ||
600 | 312 | label: QT_TR_NOOP("15 seconds") | ||
601 | 313 | value: 15 | ||
602 | 314 | } | ||
603 | 315 | }, | ||
604 | 316 | ListModel { | ||
605 | 317 | id: encodingQualityOptionsModel | ||
606 | 318 | |||
607 | 319 | property string settingsProperty: "encodingQuality" | ||
608 | 320 | property string icon: "stock_image" | ||
609 | 321 | property string label: "" | ||
610 | 322 | property bool isToggle: false | ||
611 | 323 | property int selectedIndex: bottomEdge.indexForValue(encodingQualityOptionsModel, settings.encodingQuality) | ||
612 | 324 | property bool available: true | ||
613 | 325 | property bool visible: camera.captureMode == Camera.CaptureStillImage | ||
614 | 326 | property bool showInIndicators: false | ||
615 | 327 | |||
616 | 328 | ListElement { | ||
617 | 329 | label: QT_TR_NOOP("Fine Quality") | ||
618 | 330 | value: 4 // QMultimedia.VeryHighQuality | ||
619 | 331 | } | ||
620 | 332 | ListElement { | ||
621 | 333 | label: QT_TR_NOOP("Normal Quality") | ||
622 | 334 | value: 2 // QMultimedia.NormalQuality | ||
623 | 335 | } | ||
624 | 336 | ListElement { | ||
625 | 337 | label: QT_TR_NOOP("Basic Quality") | ||
626 | 338 | value: 1 // QMultimedia.LowQuality | ||
627 | 339 | } | ||
628 | 340 | }, | ||
629 | 341 | ListModel { | ||
630 | 342 | id: gridOptionsModel | ||
631 | 343 | |||
632 | 344 | property string settingsProperty: "gridEnabled" | ||
633 | 345 | property string icon: "" | ||
634 | 346 | property string iconSource: "assets/grid_lines.svg" | ||
635 | 347 | property string label: "" | ||
636 | 348 | property bool isToggle: true | ||
637 | 349 | property int selectedIndex: bottomEdge.indexForValue(gridOptionsModel, settings.gridEnabled) | ||
638 | 350 | property bool available: true | ||
639 | 351 | property bool visible: true | ||
640 | 352 | |||
641 | 353 | ListElement { | ||
642 | 354 | icon: "" | ||
643 | 355 | label: QT_TR_NOOP("On") | ||
644 | 356 | value: true | ||
645 | 357 | } | ||
646 | 358 | ListElement { | ||
647 | 359 | icon: "" | ||
648 | 360 | label: QT_TR_NOOP("Off") | ||
649 | 361 | value: false | ||
650 | 362 | } | ||
651 | 363 | }, | ||
652 | 364 | ListModel { | ||
653 | 365 | id: removableStorageOptionsModel | ||
654 | 366 | |||
655 | 367 | property string settingsProperty: "preferRemovableStorage" | ||
656 | 368 | property string icon: "" | ||
657 | 369 | property string label: i18n.tr("SD") | ||
658 | 370 | property bool isToggle: true | ||
659 | 371 | property int selectedIndex: bottomEdge.indexForValue(removableStorageOptionsModel, settings.preferRemovableStorage) | ||
660 | 372 | property bool available: application.removableStoragePresent | ||
661 | 373 | property bool visible: available | ||
662 | 374 | |||
663 | 375 | ListElement { | ||
664 | 376 | icon: "" | ||
665 | 377 | label: QT_TR_NOOP("Save to SD Card") | ||
666 | 378 | value: true | ||
667 | 379 | } | ||
668 | 380 | ListElement { | ||
669 | 381 | icon: "" | ||
670 | 382 | label: QT_TR_NOOP("Save internally") | ||
671 | 383 | value: false | ||
672 | 384 | } | ||
673 | 385 | }, | ||
674 | 386 | ListModel { | ||
675 | 387 | id: videoResolutionOptionsModel | ||
676 | 388 | |||
677 | 389 | property string settingsProperty: "videoResolution" | ||
678 | 390 | property string icon: "" | ||
679 | 391 | property string label: "HD" | ||
680 | 392 | property bool isToggle: false | ||
681 | 393 | property int selectedIndex: bottomEdge.indexForValue(videoResolutionOptionsModel, settings.videoResolution) | ||
682 | 394 | property bool available: true | ||
683 | 395 | property bool visible: camera.captureMode == Camera.CaptureVideo | ||
684 | 396 | property bool showInIndicators: false | ||
685 | 397 | } | ||
686 | 398 | ] | ||
687 | 399 | |||
688 | 400 | /* FIXME: application.removableStoragePresent is not updated dynamically. | ||
689 | 401 | Workaround that by reading it when the bottom edge is opened/closed. | ||
690 | 402 | */ | ||
691 | 403 | Connections { | ||
692 | 404 | target: bottomEdge | ||
693 | 405 | onOpenedChanged: removableStorageOptionsModel.available = application.removableStoragePresent | ||
694 | 406 | } | ||
695 | 407 | |||
696 | 408 | function indexForValue(model, value) { | ||
697 | 409 | var i; | ||
698 | 410 | var element; | ||
699 | 411 | for (i=0; i<model.count; i++) { | ||
700 | 412 | element = model.get(i); | ||
701 | 413 | if (element.value === value) { | ||
702 | 414 | return i; | ||
703 | 415 | } | ||
704 | 416 | } | ||
705 | 417 | |||
706 | 418 | return -1; | ||
707 | 419 | } | ||
708 | 420 | |||
709 | 421 | BottomEdgeIndicators { | ||
710 | 422 | id: bottomEdgeIndicators | ||
711 | 423 | options: bottomEdge.options | ||
712 | 424 | anchors { | ||
713 | 425 | horizontalCenter: parent.horizontalCenter | ||
714 | 426 | bottom: parent.top | ||
715 | 427 | } | ||
716 | 428 | opacity: bottomEdge.pressed || bottomEdge.opened ? 0.0 : 1.0 | ||
717 | 429 | Behavior on opacity { UbuntuNumberAnimation {} } | ||
718 | 430 | } | ||
719 | 431 | |||
720 | 432 | Loader { | ||
721 | 433 | id: optionsOverlayLoader | ||
722 | 434 | anchors { | ||
723 | 435 | left: parent.left | ||
724 | 436 | right: parent.right | ||
725 | 437 | top: parent.top | ||
726 | 438 | } | ||
727 | 439 | asynchronous: true | ||
728 | 440 | sourceComponent: Component { | ||
729 | 441 | OptionsOverlay { | ||
730 | 442 | options: bottomEdge.options | ||
731 | 443 | } | ||
732 | 444 | } | ||
733 | 445 | } | ||
734 | 425 | } | 446 | } |
735 | 426 | } | 447 | } |
736 | 427 | 448 | ||
737 | @@ -438,7 +459,7 @@ | |||
738 | 438 | right: parent.right | 459 | right: parent.right |
739 | 439 | } | 460 | } |
740 | 440 | height: parent.height | 461 | height: parent.height |
742 | 441 | y: bottomEdge.position - bottomEdge.height | 462 | y: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation) == 0 ? bottomEdge.position - bottomEdge.height : 0 |
743 | 442 | opacity: 1 - bottomEdge.progress | 463 | opacity: 1 - bottomEdge.progress |
744 | 443 | visible: opacity != 0.0 | 464 | visible: opacity != 0.0 |
745 | 444 | enabled: visible | 465 | enabled: visible |
746 | @@ -656,9 +677,11 @@ | |||
747 | 656 | anchors { | 677 | anchors { |
748 | 657 | top: parent.top | 678 | top: parent.top |
749 | 658 | bottom: shootButton.top | 679 | bottom: shootButton.top |
751 | 659 | bottomMargin: units.gu(1) | 680 | bottomMargin: bottomEdgeIndicators.height |
752 | 660 | left: parent.left | 681 | left: parent.left |
753 | 682 | leftMargin: bottomEdgeIndicators.height | ||
754 | 661 | right: parent.right | 683 | right: parent.right |
755 | 684 | rightMargin: bottomEdgeIndicators.height | ||
756 | 662 | } | 685 | } |
757 | 663 | 686 | ||
758 | 664 | property real initialZoom | 687 | property real initialZoom |
759 | @@ -777,19 +800,4 @@ | |||
760 | 777 | } | 800 | } |
761 | 778 | } | 801 | } |
762 | 779 | } | 802 | } |
763 | 780 | |||
764 | 781 | Loader { | ||
765 | 782 | id: optionsOverlayLoader | ||
766 | 783 | anchors { | ||
767 | 784 | left: parent.left | ||
768 | 785 | right: parent.right | ||
769 | 786 | top: controls.bottom | ||
770 | 787 | } | ||
771 | 788 | asynchronous: true | ||
772 | 789 | sourceComponent: Component { | ||
773 | 790 | OptionsOverlay { | ||
774 | 791 | options: bottomEdge.options | ||
775 | 792 | } | ||
776 | 793 | } | ||
777 | 794 | } | ||
778 | 795 | } | 803 | } |
779 | 796 | 804 | ||
780 | === modified file 'ViewFinderView.qml' | |||
781 | --- ViewFinderView.qml 2015-01-24 12:52:12 +0000 | |||
782 | +++ ViewFinderView.qml 2015-07-03 18:21:53 +0000 | |||
783 | @@ -296,7 +296,7 @@ | |||
784 | 296 | onInViewChanged: if (!viewFinderView.inView) viewFinderOverlay.controls.cancelTimedShoot() | 296 | onInViewChanged: if (!viewFinderView.inView) viewFinderOverlay.controls.cancelTimedShoot() |
785 | 297 | } | 297 | } |
786 | 298 | 298 | ||
788 | 299 | Item { | 299 | OrientationHelper { |
789 | 300 | id: timedShootFeedback | 300 | id: timedShootFeedback |
790 | 301 | anchors.fill: parent | 301 | anchors.fill: parent |
791 | 302 | 302 | ||
792 | 303 | 303 | ||
793 | === modified file 'camera-app.desktop.in.in' | |||
794 | --- camera-app.desktop.in.in 2014-09-03 18:52:03 +0000 | |||
795 | +++ camera-app.desktop.in.in 2015-07-03 18:21:53 +0000 | |||
796 | @@ -10,3 +10,4 @@ | |||
797 | 10 | X-Ubuntu-Touch=true | 10 | X-Ubuntu-Touch=true |
798 | 11 | X-Ubuntu-Single-Instance=true | 11 | X-Ubuntu-Single-Instance=true |
799 | 12 | X-Ubuntu-Default-Department-ID=accessories | 12 | X-Ubuntu-Default-Department-ID=accessories |
800 | 13 | X-Ubuntu-Rotates-Window-Contents=true | ||
801 | 13 | 14 | ||
802 | === modified file 'camera-app.qml' | |||
803 | --- camera-app.qml 2015-04-24 12:12:23 +0000 | |||
804 | +++ camera-app.qml 2015-07-03 18:21:53 +0000 | |||
805 | @@ -69,10 +69,66 @@ | |||
806 | 69 | Flickable { | 69 | Flickable { |
807 | 70 | id: viewSwitcher | 70 | id: viewSwitcher |
808 | 71 | anchors.fill: parent | 71 | anchors.fill: parent |
810 | 72 | flickableDirection: Flickable.HorizontalFlick | 72 | flickableDirection: state == "PORTRAIT" ? Flickable.HorizontalFlick : Flickable.VerticalFlick |
811 | 73 | boundsBehavior: Flickable.StopAtBounds | 73 | boundsBehavior: Flickable.StopAtBounds |
814 | 74 | contentWidth: contentItem.childrenRect.width | 74 | |
815 | 75 | contentHeight: contentItem.childrenRect.height | 75 | property real panesMargin: units.gu(1) |
816 | 76 | property real ratio | ||
817 | 77 | property int orientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation) | ||
818 | 78 | property var angleToOrientation: {0: "PORTRAIT", | ||
819 | 79 | 90: "LANDSCAPE", | ||
820 | 80 | 270: "INVERTED_LANDSCAPE"} | ||
821 | 81 | state: angleToOrientation[orientationAngle] | ||
822 | 82 | states: [ | ||
823 | 83 | State { | ||
824 | 84 | name: "PORTRAIT" | ||
825 | 85 | StateChangeScript { | ||
826 | 86 | script: { | ||
827 | 87 | viewSwitcher.ratio = viewSwitcher.ratio; | ||
828 | 88 | viewSwitcher.contentWidth = Qt.binding(function() { return viewSwitcher.width * 2 + viewSwitcher.panesMargin }); | ||
829 | 89 | viewSwitcher.contentHeight = Qt.binding(function() { return viewSwitcher.height }); | ||
830 | 90 | galleryView.x = Qt.binding(function() { return viewFinderView.width + viewSwitcher.panesMargin }); | ||
831 | 91 | galleryView.y = 0; | ||
832 | 92 | viewFinderView.x = 0; | ||
833 | 93 | viewFinderView.y = 0; | ||
834 | 94 | viewSwitcher.contentX = viewSwitcher.ratio * viewSwitcher.contentWidth; | ||
835 | 95 | viewSwitcher.ratio = Qt.binding(function() { return viewSwitcher.contentX / viewSwitcher.contentWidth }); | ||
836 | 96 | } | ||
837 | 97 | } | ||
838 | 98 | }, | ||
839 | 99 | State { | ||
840 | 100 | name: "LANDSCAPE" | ||
841 | 101 | StateChangeScript { | ||
842 | 102 | script: { | ||
843 | 103 | viewSwitcher.ratio = viewSwitcher.ratio; | ||
844 | 104 | viewSwitcher.contentWidth = Qt.binding(function() { return viewSwitcher.width }); | ||
845 | 105 | viewSwitcher.contentHeight = Qt.binding(function() { return viewSwitcher.height * 2 + viewSwitcher.panesMargin }); | ||
846 | 106 | galleryView.x = 0; | ||
847 | 107 | galleryView.y = Qt.binding(function() { return viewFinderView.height + viewSwitcher.panesMargin }); | ||
848 | 108 | viewFinderView.x = 0; | ||
849 | 109 | viewFinderView.y = 0; | ||
850 | 110 | viewSwitcher.contentY = viewSwitcher.ratio * viewSwitcher.contentHeight; | ||
851 | 111 | viewSwitcher.ratio = Qt.binding(function() { return viewSwitcher.contentY / viewSwitcher.contentHeight }); | ||
852 | 112 | } | ||
853 | 113 | } | ||
854 | 114 | }, | ||
855 | 115 | State { | ||
856 | 116 | name: "INVERTED_LANDSCAPE" | ||
857 | 117 | StateChangeScript { | ||
858 | 118 | script: { | ||
859 | 119 | viewSwitcher.ratio = viewSwitcher.ratio; | ||
860 | 120 | viewSwitcher.contentWidth = Qt.binding(function() { return viewSwitcher.width }); | ||
861 | 121 | viewSwitcher.contentHeight = Qt.binding(function() { return viewSwitcher.height * 2 + viewSwitcher.panesMargin }); | ||
862 | 122 | galleryView.x = 0; | ||
863 | 123 | galleryView.y = 0; | ||
864 | 124 | viewFinderView.x = 0; | ||
865 | 125 | viewFinderView.y = Qt.binding(function() { return galleryView.height + viewSwitcher.panesMargin }); | ||
866 | 126 | viewSwitcher.contentY = (0.5 - viewSwitcher.ratio) * viewSwitcher.contentHeight; | ||
867 | 127 | viewSwitcher.ratio = Qt.binding(function() { return 0.5 - viewSwitcher.contentY / viewSwitcher.contentHeight }); | ||
868 | 128 | } | ||
869 | 129 | } | ||
870 | 130 | } | ||
871 | 131 | ] | ||
872 | 76 | interactive: !viewFinderView.touchAcquired && !galleryView.touchAcquired | 132 | interactive: !viewFinderView.touchAcquired && !galleryView.touchAcquired |
873 | 77 | 133 | ||
874 | 78 | Component.onCompleted: { | 134 | Component.onCompleted: { |
875 | @@ -90,20 +146,35 @@ | |||
876 | 90 | function settle() { | 146 | function settle() { |
877 | 91 | settling = true; | 147 | settling = true; |
878 | 92 | var velocity; | 148 | var velocity; |
882 | 93 | if (horizontalVelocity < 0 || visibleArea.xPosition <= 0.05 || (horizontalVelocity == 0 && visibleArea.xPosition <= 0.25)) { | 149 | if (flickableDirection == Flickable.HorizontalFlick) { |
883 | 94 | // FIXME: compute velocity better to ensure it reaches rest position (maybe in a constant time) | 150 | if (horizontalVelocity < 0 || visibleArea.xPosition <= 0.05 || (horizontalVelocity == 0 && visibleArea.xPosition <= 0.25)) { |
884 | 95 | velocity = settleVelocity; | 151 | // FIXME: compute velocity better to ensure it reaches rest position (maybe in a constant time) |
885 | 152 | velocity = settleVelocity; | ||
886 | 153 | } else { | ||
887 | 154 | velocity = -settleVelocity; | ||
888 | 155 | } | ||
889 | 156 | flick(velocity, 0); | ||
890 | 96 | } else { | 157 | } else { |
892 | 97 | velocity = -settleVelocity; | 158 | if (verticalVelocity < 0 || visibleArea.yPosition <= 0.05 || (verticalVelocity == 0 && visibleArea.yPosition <= 0.25)) { |
893 | 159 | // FIXME: compute velocity better to ensure it reaches rest position (maybe in a constant time) | ||
894 | 160 | velocity = settleVelocity; | ||
895 | 161 | } else { | ||
896 | 162 | velocity = -settleVelocity; | ||
897 | 163 | } | ||
898 | 164 | flick(0, velocity); | ||
899 | 98 | } | 165 | } |
900 | 99 | |||
901 | 100 | flick(velocity, 0); | ||
902 | 101 | } | 166 | } |
903 | 102 | 167 | ||
904 | 103 | function switchToViewFinder() { | 168 | function switchToViewFinder() { |
905 | 104 | cancelFlick(); | 169 | cancelFlick(); |
906 | 105 | switching = true; | 170 | switching = true; |
908 | 106 | flick(settleVelocity, 0); | 171 | if (state == "PORTRAIT") { |
909 | 172 | flick(settleVelocity, 0); | ||
910 | 173 | } else if (state == "LANDSCAPE") { | ||
911 | 174 | flick(0, settleVelocity); | ||
912 | 175 | } else if (state == "INVERTED_LANDSCAPE") { | ||
913 | 176 | flick(0, -settleVelocity); | ||
914 | 177 | } | ||
915 | 107 | } | 178 | } |
916 | 108 | 179 | ||
917 | 109 | onMovementEnded: { | 180 | onMovementEnded: { |
918 | @@ -139,39 +210,51 @@ | |||
919 | 139 | } | 210 | } |
920 | 140 | } | 211 | } |
921 | 141 | 212 | ||
955 | 142 | Row { | 213 | onFlickingVerticallyChanged: { |
956 | 143 | id: viewsRow | 214 | // use flickingHorizontallyChanged instead of flickEnded because flickEnded |
957 | 144 | anchors { | 215 | // is not called when a flick is interrupted by the user |
958 | 145 | top: parent.top | 216 | if (!flickingVertically) { |
959 | 146 | bottom: parent.bottom | 217 | if (settling) { |
960 | 147 | } | 218 | settling = false; |
961 | 148 | spacing: units.gu(1) | 219 | } |
962 | 149 | 220 | if (switching) { | |
963 | 150 | ViewFinderView { | 221 | switching = true; |
964 | 151 | id: viewFinderView | 222 | } |
965 | 152 | width: viewSwitcher.width | 223 | } |
966 | 153 | height: viewSwitcher.height | 224 | } |
967 | 154 | overlayVisible: !viewSwitcher.moving && !viewSwitcher.flicking | 225 | |
968 | 155 | inView: !viewSwitcher.atXEnd | 226 | onVerticalVelocityChanged: { |
969 | 156 | opacity: inView ? 1.0 : 0.0 | 227 | // FIXME: this is a workaround for the lack of notification when |
970 | 157 | onPhotoTaken: { | 228 | // the user manually interrupts a flick by pressing and releasing |
971 | 158 | galleryView.prependMediaToModel(filePath); | 229 | if (verticalVelocity == 0 && !atYBeginning && !atYEnd && !settling && !moving) { |
972 | 159 | galleryView.showLastPhotoTaken(); | 230 | settle(); |
973 | 160 | } | 231 | } |
974 | 161 | onVideoShot: { | 232 | } |
975 | 162 | galleryView.prependMediaToModel(filePath); | 233 | |
976 | 163 | galleryView.showLastPhotoTaken(); | 234 | ViewFinderView { |
977 | 164 | } | 235 | id: viewFinderView |
978 | 165 | } | 236 | width: viewSwitcher.width |
979 | 166 | 237 | height: viewSwitcher.height | |
980 | 167 | GalleryViewLoader { | 238 | overlayVisible: !viewSwitcher.moving && !viewSwitcher.flicking |
981 | 168 | id: galleryView | 239 | inView: viewSwitcher.ratio < 0.5 |
982 | 169 | width: viewSwitcher.width | 240 | opacity: inView ? 1.0 : 0.0 |
983 | 170 | height: viewSwitcher.height | 241 | onPhotoTaken: { |
984 | 171 | inView: !viewSwitcher.atXBeginning | 242 | galleryView.prependMediaToModel(filePath); |
985 | 172 | onExit: viewSwitcher.switchToViewFinder() | 243 | galleryView.showLastPhotoTaken(); |
986 | 173 | opacity: inView ? 1.0 : 0.0 | 244 | } |
987 | 174 | } | 245 | onVideoShot: { |
988 | 246 | galleryView.prependMediaToModel(filePath); | ||
989 | 247 | galleryView.showLastPhotoTaken(); | ||
990 | 248 | } | ||
991 | 249 | } | ||
992 | 250 | |||
993 | 251 | GalleryViewLoader { | ||
994 | 252 | id: galleryView | ||
995 | 253 | width: viewSwitcher.width | ||
996 | 254 | height: viewSwitcher.height | ||
997 | 255 | inView: viewSwitcher.ratio > 0.0 | ||
998 | 256 | onExit: viewSwitcher.switchToViewFinder() | ||
999 | 257 | opacity: inView ? 1.0 : 0.0 | ||
1000 | 175 | } | 258 | } |
1001 | 176 | } | 259 | } |
1002 | 177 | 260 | ||
1003 | 178 | 261 | ||
1004 | === modified file 'tests/autopilot/camera_app/tests/test_flash.py' | |||
1005 | --- tests/autopilot/camera_app/tests/test_flash.py 2015-07-03 18:21:53 +0000 | |||
1006 | +++ tests/autopilot/camera_app/tests/test_flash.py 2015-07-03 18:21:53 +0000 | |||
1007 | @@ -112,12 +112,13 @@ | |||
1008 | 112 | self.assertThat(flash_button.iconName, Equals("flash-on")) | 112 | self.assertThat(flash_button.iconName, Equals("flash-on")) |
1009 | 113 | 113 | ||
1010 | 114 | # closes the flash options menu and open the hdr options menu | 114 | # closes the flash options menu and open the hdr options menu |
1011 | 115 | self.pointing_device.move_to_object(flash_button) | ||
1012 | 116 | self.pointing_device.click() | ||
1013 | 117 | self.assertThat( | ||
1014 | 118 | option_value_selector.visible, Eventually(Equals(False))) | ||
1015 | 115 | self.pointing_device.move_to_object(hdr_button) | 119 | self.pointing_device.move_to_object(hdr_button) |
1016 | 116 | self.pointing_device.click() | 120 | self.pointing_device.click() |
1017 | 117 | self.assertThat( | 121 | self.assertThat( |
1018 | 118 | option_value_selector.visible, Eventually(Equals(False))) | ||
1019 | 119 | self.pointing_device.click() | ||
1020 | 120 | self.assertThat( | ||
1021 | 121 | option_value_selector.visible, Eventually(Equals(True))) | 122 | option_value_selector.visible, Eventually(Equals(True))) |
1022 | 122 | 123 | ||
1023 | 123 | # set hdr to "on" and verify that flash is "off" | 124 | # set hdr to "on" and verify that flash is "off" |
1024 | @@ -128,12 +129,13 @@ | |||
1025 | 128 | self.assertThat(hdr_button.on, Equals(True)) | 129 | self.assertThat(hdr_button.on, Equals(True)) |
1026 | 129 | 130 | ||
1027 | 130 | # closes the hdr options menu and open the flash options menu | 131 | # closes the hdr options menu and open the flash options menu |
1028 | 132 | self.pointing_device.move_to_object(hdr_button) | ||
1029 | 133 | self.pointing_device.click() | ||
1030 | 134 | self.assertThat( | ||
1031 | 135 | option_value_selector.visible, Eventually(Equals(False))) | ||
1032 | 131 | self.pointing_device.move_to_object(flash_button) | 136 | self.pointing_device.move_to_object(flash_button) |
1033 | 132 | self.pointing_device.click() | 137 | self.pointing_device.click() |
1034 | 133 | self.assertThat( | 138 | self.assertThat( |
1035 | 134 | option_value_selector.visible, Eventually(Equals(False))) | ||
1036 | 135 | self.pointing_device.click() | ||
1037 | 136 | self.assertThat( | ||
1038 | 137 | option_value_selector.visible, Eventually(Equals(True))) | 139 | option_value_selector.visible, Eventually(Equals(True))) |
1039 | 138 | 140 | ||
1040 | 139 | # set flash to "on" and verify that hdr is "off" | 141 | # set flash to "on" and verify that hdr is "off" |
FAILED: Continuous integration, rev:567 jenkins. qa.ubuntu. com/job/ camera- app-ci/ 428/ jenkins. qa.ubuntu. com/job/ camera- app-vivid- amd64-ci/ 124 jenkins. qa.ubuntu. com/job/ camera- app-vivid- armhf-ci/ 124 jenkins. qa.ubuntu. com/job/ camera- app-vivid- armhf-ci/ 124/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ camera- app-vivid- i386-ci/ 124 jenkins. qa.ubuntu. com/job/ generic- click-autopilot -vivid- touch/236 jenkins. qa.ubuntu. com/job/ generic- click-autopilot -runner- mako/888 jenkins. qa.ubuntu. com/job/ generic- click-builder- vivid-armhf/ 639 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 21555
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/camera- app-ci/ 428/rebuild
http://