Merge lp:~uriboni/camera-app/real-picture-snapshot into lp:camera-app/staging
- real-picture-snapshot
- Merge into staging
Status: | Rejected |
---|---|
Rejected by: | Florian Boucault |
Proposed branch: | lp:~uriboni/camera-app/real-picture-snapshot |
Merge into: | lp:camera-app/staging |
Diff against target: |
401 lines (+143/-68) 5 files modified
ProcessingFeedback.qml (+43/-0) Snapshot.qml (+25/-17) ViewFinderExportConfirmation.qml (+6/-20) ViewFinderOverlay.qml (+11/-1) ViewFinderView.qml (+58/-30) |
To merge this branch: | bzr merge lp:~uriboni/camera-app/real-picture-snapshot |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ubuntu Phablet Team | Pending | ||
Review via email: mp+283812@code.launchpad.net |
Commit message
Use the final picture as the sliding snapshot instead of the preview
Description of the change
Use the final picture as the sliding snapshot instead of the preview
PS Jenkins bot (ps-jenkins) wrote : | # |
- 642. By Ugo Riboni
-
Merge Florian's fixes
- 643. By Ugo Riboni
-
Go back to using a preview, which the backend now creates from the actual image before saving it to disk
- 644. By Ugo Riboni
-
Keep the controls always visible and below the snapshot while it slides
- 645. By Ugo Riboni
-
Ensure everything works properly when exporting pictures
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:645
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 646. By Ugo Riboni
-
On media export prevent the screen from turning black while the snapshot loads
- 647. By Ugo Riboni
-
Remove unused properties
- 648. By Ugo Riboni
-
Refactor the export confirmation so it does not use identifiers out of scope
- 649. By Ugo Riboni
-
Remove debug
- 650. By Ugo Riboni
-
Pulse the shoot button while the capture is in progress to indicate progress
- 651. By Ugo Riboni
-
Simplify code
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:646
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:651
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 652. By Ugo Riboni
-
Ensure the photo roll hint is below the snapshot and that it does not become visible too early
- 653. By Ugo Riboni
-
Merge from parent branch
- 654. By Ugo Riboni
-
Merge more fixes from another branch
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:652
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:654
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
Preview Diff
1 | === added file 'ProcessingFeedback.qml' |
2 | --- ProcessingFeedback.qml 1970-01-01 00:00:00 +0000 |
3 | +++ ProcessingFeedback.qml 2016-01-28 15:06:01 +0000 |
4 | @@ -0,0 +1,43 @@ |
5 | +/* |
6 | + * Copyright 2016 Canonical Ltd. |
7 | + * |
8 | + * This program is free software; you can redistribute it and/or modify |
9 | + * it under the terms of the GNU General Public License as published by |
10 | + * the Free Software Foundation; version 3. |
11 | + * |
12 | + * This program is distributed in the hope that it will be useful, |
13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | + * GNU General Public License for more details. |
16 | + * |
17 | + * You should have received a copy of the GNU General Public License |
18 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | + */ |
20 | + |
21 | +import QtQuick 2.4 |
22 | +import Ubuntu.Components 1.3 |
23 | + |
24 | +Item { |
25 | + id: processingFeedback |
26 | + |
27 | + property bool processing: false |
28 | + |
29 | + Timer { |
30 | + interval: 2000 |
31 | + running: processing |
32 | + onTriggered: spinner.running = true |
33 | + } |
34 | + |
35 | + onProcessingChanged: if (!processing) spinner.running = false |
36 | + |
37 | + ActivityIndicator { |
38 | + id: spinner |
39 | + opacity: running ? 1.0 : 0.0 |
40 | + Behavior on opacity { |
41 | + OpacityAnimator { |
42 | + duration: UbuntuAnimation.SnapDuration |
43 | + easing: UbuntuAnimation.StandardEasing |
44 | + } |
45 | + } |
46 | + } |
47 | +} |
48 | |
49 | === modified file 'Snapshot.qml' |
50 | --- Snapshot.qml 2015-10-22 12:21:14 +0000 |
51 | +++ Snapshot.qml 2016-01-28 15:06:01 +0000 |
52 | @@ -21,17 +21,19 @@ |
53 | Item { |
54 | id: snapshotRoot |
55 | property alias source: snapshot.source |
56 | - property alias sliding: shoot.running |
57 | - property int orientation |
58 | + property bool shouldSlide: true |
59 | + property bool sliding: false |
60 | property ViewFinderGeometry geometry |
61 | - property bool deviceDefaultIsPortrait: true |
62 | property bool loading: snapshot.status == Image.Loading |
63 | - |
64 | - function startOutAnimation() { |
65 | - shoot.restart() |
66 | - } |
67 | - |
68 | - visible: false |
69 | + property bool loaded: snapshot.status == Image.Ready |
70 | + |
71 | + opacity: 0.0 |
72 | + |
73 | + // Rotation and sliding direction is locked at the moment the picture is shoot |
74 | + // (in case processing is long, such as with HDR) |
75 | + function lockOrientation() { snapshot.rotation = orientationAngle } |
76 | + |
77 | + onLoadedChanged: if (loaded && shouldSlide) shoot.restart() |
78 | |
79 | Item { |
80 | id: container |
81 | @@ -42,14 +44,13 @@ |
82 | id: snapshot |
83 | anchors.centerIn: parent |
84 | anchors.verticalCenterOffset: -geometry.y |
85 | - rotation: snapshotRoot.orientation * -1 |
86 | |
87 | asynchronous: true |
88 | cache: false |
89 | fillMode: Image.PreserveAspectFit |
90 | smooth: false |
91 | - width: deviceDefaultIsPortrait ? geometry.height : geometry.width |
92 | - height: deviceDefaultIsPortrait ? geometry.width : geometry.height |
93 | + width: rotation == 0 ? geometry.width : geometry.height |
94 | + height: rotation == 0 ? geometry.height : geometry.width |
95 | sourceSize.width: width |
96 | sourceSize.height: height |
97 | } |
98 | @@ -57,10 +58,12 @@ |
99 | Image { |
100 | id: shadow |
101 | |
102 | - property bool rotated: (snapshot.rotation % 180) != 0 |
103 | - height: rotated ? snapshot.width : snapshot.height |
104 | + transformOrigin: Item.TopLeft |
105 | + rotation: snapshot.rotation |
106 | width: units.gu(2) |
107 | - x: (container.width - (rotated ? snapshot.height : snapshot.width)) / 2 - width |
108 | + height: rotation == 0 ? snapshot.height : snapshot.width |
109 | + x: rotation == 90 ? container.width : - width |
110 | + y: rotation == 270 ? container.height + width : (rotation == 90 ? - width : 0) |
111 | source: "assets/shadow.png" |
112 | fillMode: Image.Stretch |
113 | asynchronous: true |
114 | @@ -75,8 +78,12 @@ |
115 | SequentialAnimation { |
116 | id: shoot |
117 | |
118 | - PropertyAction { target: snapshotRoot; property: "visible"; value: true } |
119 | + NumberAnimation { |
120 | + target: snapshotRoot; property: "opacity"; to: 1.0 |
121 | + duration: UbuntuAnimation.SnapDuration |
122 | + } |
123 | PauseAnimation { duration: 150 } |
124 | + PropertyAction { target: snapshotRoot; property: "sliding"; value: true} |
125 | XAnimator { |
126 | target: container |
127 | to: angleToOrientation[orientationAngle] == "PORTRAIT" ? container.width + shadow.width : 0 |
128 | @@ -91,8 +98,9 @@ |
129 | easing: UbuntuAnimation.StandardEasing |
130 | } |
131 | PropertyAction { target: snapshot; property: "source"; value: ""} |
132 | - PropertyAction { target: snapshotRoot; property: "visible"; value: false } |
133 | + PropertyAction { target: snapshotRoot; property: "opacity"; value: 0.0 } |
134 | PropertyAction { target: container; property: "x"; value: 0 } |
135 | PropertyAction { target: container; property: "y"; value: 0 } |
136 | + PropertyAction { target: snapshotRoot; property: "sliding"; value: false} |
137 | } |
138 | } |
139 | |
140 | === modified file 'ViewFinderExportConfirmation.qml' |
141 | --- ViewFinderExportConfirmation.qml 2015-12-10 12:17:49 +0000 |
142 | +++ ViewFinderExportConfirmation.qml 2016-01-28 15:06:01 +0000 |
143 | @@ -22,23 +22,7 @@ |
144 | |
145 | property bool isVideo |
146 | property string mediaPath |
147 | - property Snapshot snapshot |
148 | - |
149 | - function confirmExport(path) { |
150 | - viewFinder.visible = false; |
151 | - viewFinderOverlay.visible = false; |
152 | - mediaPath = path; |
153 | - if (!isVideo) snapshot.visible = true; |
154 | - visible = true; |
155 | - } |
156 | - |
157 | - function hide() { |
158 | - viewFinder.visible = true; |
159 | - viewFinderOverlay.visible = true; |
160 | - snapshot.source = ""; |
161 | - snapshot.visible = false; |
162 | - visible = false; |
163 | - } |
164 | + signal hideRequested() |
165 | |
166 | visible: false |
167 | |
168 | @@ -74,7 +58,7 @@ |
169 | } |
170 | |
171 | iconName: "reload" |
172 | - onClicked: viewFinderExportConfirmation.hide() |
173 | + onClicked: hideRequested() |
174 | } |
175 | |
176 | CircleButton { |
177 | @@ -90,8 +74,9 @@ |
178 | |
179 | iconName: "ok" |
180 | onClicked: { |
181 | - viewFinderExportConfirmation.hide(); |
182 | + hideRequested(); |
183 | main.exportContent([mediaPath]); |
184 | + mediaPath = ""; |
185 | } |
186 | } |
187 | |
188 | @@ -108,8 +93,9 @@ |
189 | |
190 | iconName: "close" |
191 | onClicked: { |
192 | - viewFinderExportConfirmation.hide(); |
193 | + hideRequested(); |
194 | main.cancelExport(); |
195 | + mediaPath = ""; |
196 | } |
197 | } |
198 | } |
199 | |
200 | === modified file 'ViewFinderOverlay.qml' |
201 | --- ViewFinderOverlay.qml 2016-01-21 17:12:30 +0000 |
202 | +++ ViewFinderOverlay.qml 2016-01-28 15:06:01 +0000 |
203 | @@ -684,6 +684,7 @@ |
204 | if (!main.contentExportMode) { |
205 | shootFeedback.start(); |
206 | } |
207 | + camera.photoCaptureInProgress = true; |
208 | camera.imageCapture.setMetadata("Orientation", orientation); |
209 | var position = positionSource.position; |
210 | if (settings.gpsEnabled && positionSource.valid |
211 | @@ -698,7 +699,6 @@ |
212 | } |
213 | } |
214 | |
215 | - camera.photoCaptureInProgress = true; |
216 | if (main.contentExportMode) { |
217 | camera.imageCapture.captureToLocation(application.temporaryLocation); |
218 | } else if (application.removableStoragePresent && settings.preferRemovableStorage) { |
219 | @@ -945,6 +945,16 @@ |
220 | } |
221 | } |
222 | |
223 | + ProcessingFeedback { |
224 | + anchors { |
225 | + top: parent.top |
226 | + topMargin: units.gu(2) |
227 | + left: parent.left |
228 | + leftMargin: units.gu(2) |
229 | + } |
230 | + processing: camera.photoCaptureInProgress |
231 | + } |
232 | + |
233 | StorageMonitor { |
234 | id: storageMonitor |
235 | location: (application.removableStoragePresent && settings.preferRemovableStorage) ? |
236 | |
237 | === modified file 'ViewFinderView.qml' |
238 | --- ViewFinderView.qml 2016-01-21 16:40:19 +0000 |
239 | +++ ViewFinderView.qml 2016-01-28 15:06:01 +0000 |
240 | @@ -96,6 +96,13 @@ |
241 | property bool switchInProgress: false |
242 | property bool photoCaptureInProgress: false |
243 | |
244 | + onPhotoCaptureInProgressChanged: { |
245 | + if (photoCaptureInProgress) { |
246 | + snapshot.lockOrientation(); |
247 | + viewFinder.opacity = 0.1; |
248 | + } |
249 | + } |
250 | + |
251 | imageCapture { |
252 | onReadyChanged: { |
253 | if (camera.imageCapture.ready && main.transfer) { |
254 | @@ -110,20 +117,17 @@ |
255 | camera.photoCaptureInProgress = false; |
256 | console.log("Capture failed for request " + requestId + ": " + message); |
257 | } |
258 | - onImageCaptured: { |
259 | - snapshot.source = preview; |
260 | - if (!main.contentExportMode) { |
261 | - viewFinderOverlay.visible = true; |
262 | - snapshot.startOutAnimation(); |
263 | - if (photoRollHint.necessary) { |
264 | - photoRollHint.enable(); |
265 | - } |
266 | - } |
267 | - } |
268 | + |
269 | + onImageCaptured: snapshot.source = preview |
270 | + |
271 | onImageSaved: { |
272 | if (main.contentExportMode) { |
273 | - viewFinderExportConfirmation.confirmExport(path); |
274 | + // show export confirmation only when both the image is saved and the snapshot |
275 | + // is loaded to prevent the screen being black while the image loads |
276 | + viewFinderExportConfirmation.mediaPath = path; |
277 | + if (snapshot.loaded) viewFinderExportConfirmation.show() |
278 | } |
279 | + |
280 | viewFinderView.photoTaken(path); |
281 | camera.photoCaptureInProgress = false; |
282 | metricPhotos.increment(); |
283 | @@ -135,10 +139,10 @@ |
284 | onRecorderStateChanged: { |
285 | if (videoRecorder.recorderState === CameraRecorder.StoppedState) { |
286 | metricVideos.increment() |
287 | - viewFinderOverlay.visible = true; |
288 | viewFinderView.videoShot(videoRecorder.actualLocation); |
289 | if (main.contentExportMode) { |
290 | - viewFinderExportConfirmation.confirmExport(videoRecorder.actualLocation); |
291 | + viewFinderExportConfirmation.mediaPath = videoRecorder.actualLocation |
292 | + viewFinderExportConfirmation.show(); |
293 | } else if (photoRollHint.necessary) { |
294 | photoRollHint.enable(); |
295 | } |
296 | @@ -329,12 +333,10 @@ |
297 | anchors.fill: parent |
298 | |
299 | function start() { |
300 | - viewFinderOverlay.visible = false; |
301 | } |
302 | |
303 | function stop() { |
304 | remainingSecsLabel.text = ""; |
305 | - viewFinderOverlay.visible = true; |
306 | } |
307 | |
308 | function showRemainingSecs(secs) { |
309 | @@ -383,7 +385,6 @@ |
310 | |
311 | function start() { |
312 | shootFeedback.opacity = 1.0; |
313 | - viewFinderOverlay.visible = false; |
314 | shootFeedbackAnimation.restart(); |
315 | } |
316 | |
317 | @@ -392,7 +393,7 @@ |
318 | target: shootFeedback |
319 | from: 1.0 |
320 | to: 0.0 |
321 | - duration: 50 |
322 | + duration: UbuntuAnimation.SnapDuration |
323 | easing: UbuntuAnimation.StandardEasing |
324 | } |
325 | } |
326 | @@ -409,19 +410,10 @@ |
327 | visible: radius !== 0 |
328 | } |
329 | |
330 | - ViewFinderOverlayLoader { |
331 | - id: viewFinderOverlay |
332 | - |
333 | - anchors.fill: parent |
334 | - camera: camera |
335 | - opacity: status == Loader.Ready && overlayVisible && !photoRollHint.enabled ? 1.0 : 0.0 |
336 | - Behavior on opacity {UbuntuNumberAnimation {duration: UbuntuAnimation.SnapDuration}} |
337 | - } |
338 | - |
339 | PhotoRollHint { |
340 | id: photoRollHint |
341 | anchors.fill: parent |
342 | - visible: enabled && !snapshot.loading |
343 | + visible: enabled |
344 | |
345 | Connections { |
346 | target: viewFinderView |
347 | @@ -432,15 +424,51 @@ |
348 | Snapshot { |
349 | id: snapshot |
350 | anchors.fill: parent |
351 | - orientation: viewFinder.orientation |
352 | geometry: viewFinderGeometry |
353 | - deviceDefaultIsPortrait: Screen.primaryOrientation === Qt.PortraitOrientation |
354 | + shouldSlide: !main.contentExportMode |
355 | + onSlidingChanged: { |
356 | + if (sliding) { |
357 | + viewFinder.opacity = 1.0; |
358 | + if (!main.contentExportMode && photoRollHint.necessary) photoRollHint.enable(); |
359 | + } |
360 | + } |
361 | + |
362 | + // show export confirmation only when both the image is saved and the snapshot |
363 | + // is loaded to prevent the screen being black while the image loads |
364 | + onLoadedChanged: { |
365 | + if (main.contentExportMode && loaded && viewFinderExportConfirmation.mediaPath != "") viewFinderExportConfirmation.show() |
366 | + } |
367 | + } |
368 | + |
369 | + ViewFinderOverlayLoader { |
370 | + id: viewFinderOverlay |
371 | + |
372 | + anchors.fill: parent |
373 | + camera: camera |
374 | + opacity: status == Loader.Ready && overlayVisible && !photoRollHint.enabled ? 1.0 : 0.0 |
375 | + Behavior on opacity {UbuntuNumberAnimation {duration: UbuntuAnimation.SnapDuration}} |
376 | } |
377 | |
378 | ViewFinderExportConfirmation { |
379 | id: viewFinderExportConfirmation |
380 | anchors.fill: parent |
381 | - snapshot: snapshot |
382 | + |
383 | isVideo: main.transfer.contentType == ContentType.Videos |
384 | + onVisibleChanged: if (visible) viewFinder.opacity = 1.0 |
385 | + |
386 | + function show() { |
387 | + viewFinder.visible = false; |
388 | + viewFinderOverlay.visible = false; |
389 | + if (!isVideo) snapshot.opacity = 1.0; |
390 | + visible = true; |
391 | + } |
392 | + |
393 | + onHideRequested: { |
394 | + viewFinder.visible = true; |
395 | + viewFinderOverlay.visible = true; |
396 | + snapshot.source = ""; |
397 | + snapshot.opacity = 0.0; |
398 | + visible = false; |
399 | + } |
400 | } |
401 | } |
FAILED: Continuous integration, rev:641 jenkins. qa.ubuntu. com/job/ camera- app-staging- ci/17/ jenkins. qa.ubuntu. com/job/ camera- app-staging- vivid-amd64- ci/17 jenkins. qa.ubuntu. com/job/ camera- app-staging- vivid-amd64- ci/17/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ camera- app-staging- vivid-armhf- ci/17 jenkins. qa.ubuntu. com/job/ camera- app-staging- vivid-armhf- ci/17/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ camera- app-staging- vivid-i386- ci/17 jenkins. qa.ubuntu. com/job/ camera- app-staging- vivid-i386- ci/17/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ generic- click-autopilot -vivid- touch/378 jenkins. qa.ubuntu. com/job/ generic- click-autopilot -runner- touch/1049 jenkins. qa.ubuntu. com/job/ generic- click-builder- vivid-armhf/ 931 s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 27009
http://
Executed test runs:
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/camera- app-staging- ci/17/rebuild
http://