Merge lp:~fboucault/camera-app/fix_test_video_resolution into lp:camera-app

Proposed by Florian Boucault
Status: Superseded
Proposed branch: lp:~fboucault/camera-app/fix_test_video_resolution
Merge into: lp:camera-app
Diff against target: 768 lines (+418/-51)
10 files modified
BottomEdgeIndicators.qml (+1/-1)
CameraApp/advancedcamerasettings.cpp (+125/-0)
CameraApp/advancedcamerasettings.h (+11/-0)
OptionButton.qml (+1/-1)
ViewFinderOverlay.qml (+170/-4)
ViewFinderView.qml (+15/-16)
manifest.json.in (+1/-1)
tests/autopilot/camera_app/emulators/main_window.py (+20/-1)
tests/autopilot/camera_app/tests/test_capture.py (+27/-27)
tests/autopilot/camera_app/tests/test_zoom.py (+47/-0)
To merge this branch: bzr merge lp:~fboucault/camera-app/fix_test_video_resolution
Reviewer Review Type Date Requested Status
Ubuntu Phablet Team Pending
Review via email: mp+278981@code.launchpad.net

Commit message

Fix AP test camera_app.tests.test_capture.TestCapture.test_video_resolution_setting_switching_cameras: use selected resolution from current camera as expected resolution.

To post a comment you must log in.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'BottomEdgeIndicators.qml'
2--- BottomEdgeIndicators.qml 2015-10-22 12:21:14 +0000
3+++ BottomEdgeIndicators.qml 2015-11-30 15:11:56 +0000
4@@ -84,7 +84,7 @@
5 id: indicatorIcon
6 anchors.fill: parent
7 color: "white"
8- name: modelData && modelData.isToggle ? modelData.icon : modelData.get(model.selectedIndex).icon
9+ name: modelData && modelData.isToggle ? modelData.icon : (modelData.get(model.selectedIndex) ? modelData.get(model.selectedIndex).icon : "")
10 source: name ? "image://theme/%1".arg(name) : (modelData.iconSource || "")
11 visible: source != ""
12 }
13
14=== modified file 'CameraApp/advancedcamerasettings.cpp'
15--- CameraApp/advancedcamerasettings.cpp 2015-10-27 09:17:27 +0000
16+++ CameraApp/advancedcamerasettings.cpp 2015-11-30 15:11:56 +0000
17@@ -26,6 +26,10 @@
18 #include <QtMultimedia/QVideoDeviceSelectorControl>
19 #include <QtMultimedia/QCameraFlashControl>
20 #include <QtMultimedia/QCameraExposureControl>
21+#include <QGuiApplication>
22+#include <QScreen>
23+
24+#include <cmath>
25
26 // Definition of this enum value is duplicated in qtubuntu-camera
27 static const QCameraExposure::ExposureMode ExposureHdr = static_cast<QCameraExposure::ExposureMode>(QCameraExposure::ExposureModeVendor + 1);
28@@ -222,6 +226,12 @@
29 QObject::connect(m_cameraControl,
30 SIGNAL(captureModeChanged(QCamera::CaptureModes)),
31 this, SIGNAL(resolutionChanged()));
32+ QObject::connect(m_cameraControl,
33+ SIGNAL(captureModeChanged(QCamera::CaptureModes)),
34+ this, SIGNAL(maximumResolutionChanged()));
35+ QObject::connect(m_cameraControl,
36+ SIGNAL(captureModeChanged(QCamera::CaptureModes)),
37+ this, SIGNAL(fittingResolutionChanged()));
38 }
39
40 m_cameraFlashControl = flashControlFromCamera(m_camera);
41@@ -237,6 +247,8 @@
42 m_videoEncoderControl = videoEncoderControlFromCamera(m_camera);
43
44 Q_EMIT resolutionChanged();
45+ Q_EMIT maximumResolutionChanged();
46+ Q_EMIT fittingResolutionChanged();
47 Q_EMIT hasFlashChanged();
48 Q_EMIT hasHdrChanged();
49 Q_EMIT hdrEnabledChanged();
50@@ -260,6 +272,8 @@
51 }
52 Q_EMIT activeCameraIndexChanged();
53 Q_EMIT resolutionChanged();
54+ Q_EMIT maximumResolutionChanged();
55+ Q_EMIT fittingResolutionChanged();
56 Q_EMIT hasFlashChanged();
57 Q_EMIT videoSupportedResolutionsChanged();
58 }
59@@ -277,6 +291,117 @@
60 return QSize();
61 }
62
63+QSize AdvancedCameraSettings::imageCaptureResolution() const
64+{
65+ if (m_imageEncoderControl != 0) {
66+ return m_imageEncoderControl->imageSettings().resolution();
67+ }
68+
69+ return QSize();
70+}
71+
72+QSize AdvancedCameraSettings::videoRecorderResolution() const
73+{
74+ if (m_videoEncoderControl != 0) {
75+ return m_videoEncoderControl->videoSettings().resolution();
76+ }
77+
78+ return QSize();
79+}
80+
81+QSize AdvancedCameraSettings::maximumResolution() const
82+{
83+ if (m_imageEncoderControl) {
84+ QList<QSize> sizes = m_imageEncoderControl->supportedResolutions(
85+ m_imageEncoderControl->imageSettings());
86+
87+ QSize maximumSize;
88+ long maximumPixels = 0;
89+
90+ QList<QSize>::const_iterator it = sizes.begin();
91+ while (it != sizes.end()) {
92+ const long pixels = ((long)((*it).width())) * ((long)((*it).height()));
93+ if (pixels > maximumPixels) {
94+ maximumSize = *it;
95+ maximumPixels = pixels;
96+ }
97+ ++it;
98+ }
99+
100+ return maximumSize;
101+ }
102+
103+ return QSize();
104+}
105+
106+float AdvancedCameraSettings::getScreenAspectRatio() const
107+{
108+ float screenAspectRatio;
109+ QScreen *screen = QGuiApplication::primaryScreen();
110+ Q_ASSERT(!screen);
111+ const int kScreenWidth = screen->geometry().width();
112+ const int kScreenHeight = screen->geometry().height();
113+ Q_ASSERT(kScreenWidth > 0 && kScreenHeight > 0);
114+
115+ screenAspectRatio = (kScreenWidth > kScreenHeight) ?
116+ ((float)kScreenWidth / (float)kScreenHeight) : ((float)kScreenHeight / (float)kScreenWidth);
117+
118+ return screenAspectRatio;
119+}
120+
121+QSize AdvancedCameraSettings::fittingResolution() const
122+{
123+ QList<float> prioritizedAspectRatios;
124+ prioritizedAspectRatios.append(getScreenAspectRatio());
125+ const float backAspectRatios[4] = { 16.0f/9.0f, 3.0f/2.0f, 4.0f/3.0f, 5.0f/4.0f };
126+ for (int i=0; i<4; ++i) {
127+ if (!prioritizedAspectRatios.contains(backAspectRatios[i])) {
128+ prioritizedAspectRatios.append(backAspectRatios[i]);
129+ }
130+ }
131+
132+ if (m_imageEncoderControl) {
133+ QList<QSize> sizes = m_imageEncoderControl->supportedResolutions(
134+ m_imageEncoderControl->imageSettings());
135+
136+ QSize optimalSize;
137+ long optimalPixels = 0;
138+
139+ if (!sizes.empty()) {
140+ float aspectRatio;
141+
142+ // Loop over all reported camera resolutions until we find the highest
143+ // one that matches the current prioritized aspect ratio. If it doesn't
144+ // find one on the current aspect ration, it selects the next ratio and
145+ // tries again.
146+ QList<float>::const_iterator ratioIt = prioritizedAspectRatios.begin();
147+ while (ratioIt != prioritizedAspectRatios.end()) {
148+ // Don't update the aspect ratio when using this function for finding
149+ // the optimal thumbnail size as it will affect the preview window size
150+ aspectRatio = (*ratioIt);
151+
152+ QList<QSize>::const_iterator it = sizes.begin();
153+ while (it != sizes.end()) {
154+ const float ratio = (float)(*it).width() / (float)(*it).height();
155+ const long pixels = ((long)((*it).width())) * ((long)((*it).height()));
156+ const float EPSILON = 0.02;
157+ if (fabs(ratio - aspectRatio) < EPSILON && pixels > optimalPixels) {
158+ optimalSize = *it;
159+ optimalPixels = pixels;
160+ }
161+ ++it;
162+ }
163+ if (optimalPixels > 0) break;
164+ ++ratioIt;
165+ }
166+ }
167+
168+ return optimalSize;
169+ }
170+
171+ return QSize();
172+}
173+
174 QStringList AdvancedCameraSettings::videoSupportedResolutions() const
175 {
176 if (m_videoEncoderControl) {
177
178=== modified file 'CameraApp/advancedcamerasettings.h'
179--- CameraApp/advancedcamerasettings.h 2014-12-08 19:12:52 +0000
180+++ CameraApp/advancedcamerasettings.h 2015-11-30 15:11:56 +0000
181@@ -40,6 +40,10 @@
182 Q_PROPERTY (int activeCameraIndex READ activeCameraIndex WRITE setActiveCameraIndex
183 NOTIFY activeCameraIndexChanged)
184 Q_PROPERTY (QSize resolution READ resolution NOTIFY resolutionChanged)
185+ Q_PROPERTY (QSize imageCaptureResolution READ imageCaptureResolution)
186+ Q_PROPERTY (QSize videoRecorderResolution READ videoRecorderResolution)
187+ Q_PROPERTY (QSize maximumResolution READ maximumResolution NOTIFY maximumResolutionChanged)
188+ Q_PROPERTY (QSize fittingResolution READ fittingResolution NOTIFY fittingResolutionChanged)
189 Q_PROPERTY (QStringList videoSupportedResolutions READ videoSupportedResolutions NOTIFY videoSupportedResolutionsChanged)
190 Q_PROPERTY (bool hasFlash READ hasFlash NOTIFY hasFlashChanged)
191 Q_PROPERTY (bool hdrEnabled READ hdrEnabled WRITE setHdrEnabled NOTIFY hdrEnabledChanged)
192@@ -53,6 +57,11 @@
193 void setCamera(QObject* camera);
194 void setActiveCameraIndex(int index);
195 QSize resolution() const;
196+ QSize imageCaptureResolution() const;
197+ QSize videoRecorderResolution() const;
198+ QSize maximumResolution() const;
199+ QSize fittingResolution() const;
200+ float getScreenAspectRatio() const;
201 QStringList videoSupportedResolutions() const;
202 bool hasFlash() const;
203 bool hasHdr() const;
204@@ -66,6 +75,8 @@
205 void cameraChanged();
206 void activeCameraIndexChanged();
207 void resolutionChanged();
208+ void maximumResolutionChanged();
209+ void fittingResolutionChanged();
210 void hasFlashChanged();
211 void hasHdrChanged();
212 void hdrEnabledChanged();
213
214=== modified file 'OptionButton.qml'
215--- OptionButton.qml 2015-10-22 12:21:14 +0000
216+++ OptionButton.qml 2015-11-30 15:11:56 +0000
217@@ -23,7 +23,7 @@
218 property var model
219 property string settingsProperty: model.settingsProperty
220
221- iconName: model.isToggle || !model.get(model.selectedIndex).icon ? model.icon : model.get(model.selectedIndex).icon
222+ iconName: !model.get(model.selectedIndex).icon ? model.icon : model.get(model.selectedIndex).icon
223 iconSource: (model && model.iconSource) ? model.iconSource : ""
224 on: model.isToggle ? model.get(model.selectedIndex).value : true
225 enabled: model.available
226
227=== modified file 'ViewFinderOverlay.qml'
228--- ViewFinderOverlay.qml 2015-10-22 12:21:14 +0000
229+++ ViewFinderOverlay.qml 2015-11-30 15:11:56 +0000
230@@ -50,6 +50,13 @@
231 property bool gridEnabled: false
232 property bool preferRemovableStorage: false
233 property string videoResolution: "1920x1080"
234+ property bool playShutterSound: true
235+ // FIXME: stores the resolution selected for 2 cameras. Instead it should:
236+ // - support any number of cameras
237+ // - not rely on the camera index but on Camera.deviceId
238+ // Ref.: http://doc.qt.io/qt-5/qml-qtmultimedia-camera.html#deviceId-prop
239+ property string photoResolution0
240+ property string photoResolution1
241
242 onFlashModeChanged: if (flashMode != Camera.FlashOff) hdrEnabled = false;
243 onHdrEnabledChanged: if (hdrEnabled) flashMode = Camera.FlashOff
244@@ -87,12 +94,83 @@
245 value: settings.videoResolution
246 }
247
248+ Binding {
249+ target: camera.imageCapture
250+ property: "resolution"
251+ value: settings["photoResolution" + camera.advanced.activeCameraIndex]
252+ }
253+
254+ Connections {
255+ target: camera.imageCapture
256+ onResolutionChanged: {
257+ // FIXME: this is a necessary workaround because:
258+ // - Neither camera.viewfinder.resolution nor camera.advanced.resolution
259+ // emit a changed signal when the underlying AalViewfinderSettingsControl's
260+ // resolution changes
261+ // - we know that qtubuntu-camera changes the resolution of the
262+ // viewfinder automatically when the capture resolution is set
263+ // - we need camera.viewfinder.resolution to hold the right
264+ // value
265+ camera.viewfinder.resolution = camera.advanced.resolution;
266+ }
267+ }
268+
269+ Connections {
270+ target: camera.videoRecorder
271+ onResolutionChanged: {
272+ // FIXME: see workaround setting camera.viewfinder.resolution above
273+ camera.viewfinder.resolution = camera.advanced.resolution;
274+ }
275+ }
276+
277+ Connections {
278+ target: camera
279+ onCaptureModeChanged: {
280+ // FIXME: see workaround setting camera.viewfinder.resolution above
281+ camera.viewfinder.resolution = camera.advanced.resolution;
282+ }
283+ }
284+
285 function resolutionToLabel(resolution) {
286 // takes in a resolution string (e.g. "1920x1080") and returns a nicer
287 // form of it for display in the UI: "1080p"
288 return resolution.split("x").pop() + "p";
289 }
290
291+ function sizeToString(size) {
292+ return size.width + "x" + size.height;
293+ }
294+
295+ function stringToSize(resolution) {
296+ var r = resolution.split("x");
297+ return Qt.size(r[0], r[1]);
298+ }
299+
300+ function sizeToAspectRatio(size) {
301+ var ratio = Math.max(size.width, size.height) / Math.min(size.width, size.height);
302+ var maxDenominator = 12;
303+ var epsilon;
304+ var numerator;
305+ var denominator;
306+ var bestDenominator;
307+ var bestEpsilon = 10000;
308+ for (denominator = 2; denominator <= maxDenominator; denominator++) {
309+ numerator = ratio * denominator;
310+ epsilon = Math.abs(Math.round(numerator) - numerator);
311+ if (epsilon < bestEpsilon) {
312+ bestEpsilon = epsilon;
313+ bestDenominator = denominator;
314+ }
315+ }
316+ numerator = Math.round(ratio * bestDenominator);
317+ return "%1:%2".arg(numerator).arg(bestDenominator);
318+ }
319+
320+ function sizeToMegapixels(size) {
321+ var megapixels = (size.width * size.height) / 1000000;
322+ return parseFloat(megapixels.toFixed(1))
323+ }
324+
325 function updateVideoResolutionOptions() {
326 // Clear and refill videoResolutionOptionsModel with available resolutions
327 // Try to only display well known resolutions: 1080p, 720p and 480p
328@@ -110,25 +188,71 @@
329 }
330
331 // If resolution setting chosen is not supported select the highest available resolution
332- if (supported.indexOf(settings.videoResolution) == -1) {
333+ if (supported.length > 0 && supported.indexOf(settings.videoResolution) == -1) {
334 settings.videoResolution = supported[supported.length - 1];
335 }
336 }
337
338+ function updatePhotoResolutionOptions() {
339+ // Clear and refill photoResolutionOptionsModel with available resolutions
340+ photoResolutionOptionsModel.clear();
341+
342+ var optionMaximum = {"icon": "",
343+ "label": "%1 (%2MP)".arg(sizeToAspectRatio(camera.advanced.maximumResolution))
344+ .arg(sizeToMegapixels(camera.advanced.maximumResolution)),
345+ "value": sizeToString(camera.advanced.maximumResolution)};
346+
347+ var optionFitting = {"icon": "",
348+ "label": "%1 (%2MP)".arg(sizeToAspectRatio(camera.advanced.fittingResolution))
349+ .arg(sizeToMegapixels(camera.advanced.fittingResolution)),
350+ "value": sizeToString(camera.advanced.fittingResolution)};
351+
352+ photoResolutionOptionsModel.insert(0, optionMaximum);
353+ if (camera.advanced.fittingResolution != camera.advanced.maximumResolution) {
354+ photoResolutionOptionsModel.insert(1, optionFitting);
355+ }
356+
357+ var photoResolution = settings["photoResolution" + camera.advanced.activeCameraIndex];
358+ // If resolution setting chosen is not supported select the fitting resolution
359+ if (photoResolution != optionFitting.value &&
360+ photoResolution != optionMaximum.value) {
361+ settings["photoResolution" + camera.advanced.activeCameraIndex] = optionFitting.value;
362+ }
363+ }
364+
365 Component.onCompleted: {
366+ camera.cameraState = Camera.LoadedState;
367 updateVideoResolutionOptions();
368+ updatePhotoResolutionOptions();
369+ // FIXME: see workaround setting camera.viewfinder.resolution above
370+ camera.viewfinder.resolution = camera.advanced.resolution;
371+ camera.cameraState = Camera.ActiveState;
372 }
373
374 Connections {
375 target: camera.advanced
376 onVideoSupportedResolutionsChanged: updateVideoResolutionOptions();
377+ onFittingResolutionChanged: updatePhotoResolutionOptions();
378+ onMaximumResolutionChanged: updatePhotoResolutionOptions();
379 }
380
381 Connections {
382 target: camera.advanced
383 onActiveCameraIndexChanged: {
384+ var hasPhotoResolutionSetting = (settings["photoResolution" + camera.advanced.activeCameraIndex] != "")
385+ // FIXME: use camera.advanced.imageCaptureResolution instead of camera.imageCapture.resolution
386+ // because the latter is not updated when the backend changes the resolution
387+ settings["photoResolution" + camera.advanced.activeCameraIndex] = sizeToString(camera.advanced.imageCaptureResolution);
388+ settings.videoResolution = sizeToString(camera.advanced.videoRecorderResolution);
389+ updatePhotoResolutionOptions();
390 updateVideoResolutionOptions();
391- camera.videoRecorder.resolution = settings.videoResolution;
392+ // FIXME: see workaround setting camera.viewfinder.resolution above
393+ camera.viewfinder.resolution = camera.advanced.resolution;
394+
395+ // If no resolution has ever been chosen, select the one that fits the screen
396+ if (!hasPhotoResolutionSetting) {
397+ settings["photoResolution" + camera.advanced.activeCameraIndex] = sizeToString(camera.advanced.fittingResolution);
398+ }
399 }
400 }
401
402@@ -280,7 +404,7 @@
403 property bool isToggle: true
404 property int selectedIndex: bottomEdge.indexForValue(hdrOptionsModel, settings.hdrEnabled)
405 property bool available: camera.advanced.hasHdr
406- property bool visible: true
407+ property bool visible: camera.captureMode === Camera.CaptureStillImage
408 property bool showInIndicators: true
409
410 ListElement {
411@@ -404,6 +528,41 @@
412 property bool available: true
413 property bool visible: camera.captureMode == Camera.CaptureVideo
414 property bool showInIndicators: false
415+ },
416+ ListModel {
417+ id: shutterSoundOptionsModel
418+
419+ property string settingsProperty: "playShutterSound"
420+ property string icon: ""
421+ property string label: ""
422+ property bool isToggle: true
423+ property int selectedIndex: bottomEdge.indexForValue(shutterSoundOptionsModel, settings.playShutterSound)
424+ property bool available: true
425+ property bool visible: camera.captureMode === Camera.CaptureStillImage
426+ property bool showInIndicators: false
427+
428+ ListElement {
429+ icon: "audio-volume-high"
430+ label: QT_TR_NOOP("On")
431+ value: true
432+ }
433+ ListElement {
434+ icon: "audio-volume-muted"
435+ label: QT_TR_NOOP("Off")
436+ value: false
437+ }
438+ },
439+ ListModel {
440+ id: photoResolutionOptionsModel
441+
442+ property string settingsProperty: "photoResolution" + camera.advanced.activeCameraIndex
443+ property string icon: ""
444+ property string label: sizeToAspectRatio(stringToSize(settings[settingsProperty]))
445+ property bool isToggle: false
446+ property int selectedIndex: bottomEdge.indexForValue(photoResolutionOptionsModel, settings[settingsProperty])
447+ property bool available: true
448+ property bool visible: camera.captureMode == Camera.CaptureStillImage
449+ property bool showInIndicators: false
450 }
451 ]
452
453@@ -571,18 +730,25 @@
454 function completeSwitch() {
455 viewFinderSwitcherAnimation.restart();
456 camera.switchInProgress = false;
457+ zoomControl.value = camera.currentZoom;
458 }
459
460 function changeRecordMode() {
461 if (camera.captureMode == Camera.CaptureVideo) camera.videoRecorder.stop()
462 camera.captureMode = (camera.captureMode == Camera.CaptureVideo) ? Camera.CaptureStillImage : Camera.CaptureVideo
463+ zoomControl.value = camera.currentZoom
464+ }
465+
466+ Connections {
467+ target: Qt.application
468+ onActiveChanged: if (active) zoomControl.value = camera.currentZoom
469 }
470
471 Timer {
472 id: shootingTimer
473 repeat: true
474 triggeredOnStart: true
475-
476+
477 property int remainingSecs: 0
478
479 onTriggered: {
480
481=== modified file 'ViewFinderView.qml'
482--- ViewFinderView.qml 2015-11-16 15:54:25 +0000
483+++ ViewFinderView.qml 2015-11-30 15:11:56 +0000
484@@ -36,6 +36,7 @@
485 Camera {
486 id: camera
487 captureMode: Camera.CaptureStillImage
488+ cameraState: Camera.UnloadedState
489 StateSaver.properties: "captureMode"
490
491 function manualFocus(x, y) {
492@@ -67,10 +68,6 @@
493 StateSaver.properties: "activeCameraIndex"
494 }
495
496- Component.onCompleted: {
497- camera.start();
498- }
499-
500 /* Use only digital zoom for now as it's what phone cameras mostly use.
501 TODO: if optical zoom is available, maximumZoom should be the combined
502 range of optical and digital zoom and currentZoom should adjust the two
503@@ -121,12 +118,14 @@
504 target: Qt.application
505 onActiveChanged: {
506 if (Qt.application.active) {
507- camera.start()
508+ if (camera.cameraState == Camera.LoadedState) {
509+ camera.cameraState = Camera.ActiveState;
510+ }
511 } else if (!application.desktopMode) {
512 if (camera.videoRecorder.recorderState == CameraRecorder.RecordingState) {
513 camera.videoRecorder.stop();
514 }
515- camera.stop()
516+ camera.cameraState = Camera.LoadedState;
517 }
518 }
519 }
520@@ -250,16 +249,16 @@
521 axis.x: 0; axis.y: 1; axis.z: 0
522 angle: application.desktopMode ? 180 : 0
523 }
524-
525- ViewFinderGeometry {
526- id: viewFinderGeometry
527- anchors.centerIn: parent
528-
529- cameraResolution: camera.advanced.resolution
530- viewFinderHeight: viewFinder.height
531- viewFinderWidth: viewFinder.width
532- viewFinderOrientation: viewFinder.orientation
533- }
534+ }
535+
536+ ViewFinderGeometry {
537+ id: viewFinderGeometry
538+ anchors.centerIn: parent
539+
540+ cameraResolution: camera.viewfinder.resolution
541+ viewFinderHeight: viewFinder.height
542+ viewFinderWidth: viewFinder.width
543+ viewFinderOrientation: viewFinder.orientation
544 }
545
546 Item {
547
548=== modified file 'manifest.json.in'
549--- manifest.json.in 2015-11-23 15:07:14 +0000
550+++ manifest.json.in 2015-11-30 15:11:56 +0000
551@@ -1,6 +1,6 @@
552 {
553 "description": "An application to take pictures and videos with the device cameras",
554- "framework": "ubuntu-sdk-15.04.2",
555+ "framework": "ubuntu-sdk-15.04.3",
556 "architecture": "@CLICK_ARCH@",
557 "hooks": {
558 "camera": {
559
560=== modified file 'tests/autopilot/camera_app/emulators/main_window.py'
561--- tests/autopilot/camera_app/emulators/main_window.py 2015-11-20 15:01:02 +0000
562+++ tests/autopilot/camera_app/emulators/main_window.py 2015-11-30 15:11:56 +0000
563@@ -7,7 +7,7 @@
564
565 from camera_app.emulators.panel import Panel
566 from autopilot.matchers import Eventually
567-from testtools.matchers import Equals
568+from testtools.matchers import Equals, NotEquals
569
570
571 class MainWindow(object):
572@@ -163,3 +163,22 @@
573 tx, ty, (tx + view_switcher.width // 2), ty, rate=1)
574 viewfinder = self.get_viewfinder()
575 testCase.assertThat(viewfinder.inView, Eventually(Equals(True)))
576+
577+ def switch_cameras(self):
578+ # Swap cameras and wait for camera to settle
579+ shoot_button = self.get_exposure_button()
580+ swap_camera_button = self.get_swap_camera_button()
581+ self.app.pointing_device.move_to_object(swap_camera_button)
582+ self.app.pointing_device.click()
583+ shoot_button.enabled.wait_for(True)
584+
585+ def switch_recording_mode(self):
586+ record_control = self.get_record_control()
587+
588+ # Wait for the camera overlay to be loaded
589+ record_control.enabled.wait_for(True)
590+ record_control.width.wait_for(NotEquals(0))
591+ record_control.height.wait_for(NotEquals(0))
592+
593+ self.app.pointing_device.move_to_object(record_control)
594+ self.app.pointing_device.click()
595
596=== modified file 'tests/autopilot/camera_app/tests/test_capture.py'
597--- tests/autopilot/camera_app/tests/test_capture.py 2015-10-05 13:14:12 +0000
598+++ tests/autopilot/camera_app/tests/test_capture.py 2015-11-30 15:11:56 +0000
599@@ -90,13 +90,11 @@
600
601 """
602 # Get all the elements
603- record_control = self.main_window.get_record_control()
604 stop_watch = self.main_window.get_stop_watch()
605 exposure_button = self.main_window.get_exposure_button()
606
607 # Click the record button to toggle photo/video mode
608- self.pointing_device.move_to_object(record_control)
609- self.pointing_device.click()
610+ self.main_window.switch_recording_mode()
611
612 # Before recording the stop watch should read zero recording time
613 # and not be visible anyway.
614@@ -137,8 +135,7 @@
615 # Now stop the video and go back to picture mode and check if
616 # everything resets itself to previous states
617 self.pointing_device.click()
618- self.pointing_device.move_to_object(record_control)
619- self.pointing_device.click()
620+ self.main_window.switch_recording_mode()
621
622 self.assertThat(stop_watch.opacity, Eventually(Equals(0.0)))
623
624@@ -268,7 +265,7 @@
625 """Test recording videos at a set resolution and switching cameras"""
626 def test_video_resolution_setting_switching_cameras(self):
627 # switch to video recording and empty video folder
628- self.switch_to_video_recording()
629+ self.main_window.switch_recording_mode()
630 self.delete_all_videos()
631
632 # select the first resolution for the current camera
633@@ -277,32 +274,25 @@
634 self.set_video_resolution(initial_resolution)
635
636 # switch cameras and select the last resolution for the current camera
637- self.switch_cameras()
638+ self.main_window.switch_cameras()
639 resolutions = self.get_available_video_resolutions()
640 expected_resolution = resolutions[-1]
641 self.assertThat(expected_resolution, NotEquals(initial_resolution))
642 self.set_video_resolution(expected_resolution)
643
644 # switch back to the initial camera and record a video
645- self.switch_cameras()
646+ self.main_window.switch_cameras()
647 self.record_video(2)
648 video_file = self.get_first_video()
649 height = self.read_video_height(video_file)
650+ expected_resolution = self.get_selected_video_resolution()
651 expected_height = self.height_from_resolution_label(
652 expected_resolution)
653 self.assertThat(height, Equals(expected_height))
654
655- def switch_cameras(self):
656- # Swap cameras and wait for camera to settle
657- shoot_button = self.main_window.get_exposure_button()
658- swap_camera_button = self.main_window.get_swap_camera_button()
659- self.pointing_device.move_to_object(swap_camera_button)
660- self.pointing_device.click()
661- self.assertThat(shoot_button.enabled, Eventually(Equals(True)))
662-
663 """Test recording videos at various resolutions"""
664 def test_video_resolution_setting(self):
665- self.switch_to_video_recording()
666+ self.main_window.switch_recording_mode()
667 resolutions = self.get_available_video_resolutions()
668
669 for resolution_label in resolutions:
670@@ -316,16 +306,6 @@
671 self.assertThat(height, Equals(expected_height))
672 self.dismiss_first_photo_hint()
673
674- def switch_to_video_recording(self):
675- record_control = self.main_window.get_record_control()
676- # Wait for the camera overlay to be loaded
677- self.assertThat(record_control.enabled, Eventually(Equals(True)))
678- self.assertThat(record_control.width, Eventually(NotEquals(0)))
679- self.assertThat(record_control.height, Eventually(NotEquals(0)))
680-
681- self.pointing_device.move_to_object(record_control)
682- self.pointing_device.click()
683-
684 def get_available_video_resolutions(self):
685 # open bottom edge
686 bottom_edge = self.main_window.get_bottom_edge()
687@@ -346,6 +326,26 @@
688 bottom_edge.close()
689 return resolutions
690
691+ def get_selected_video_resolution(self):
692+ # open bottom edge
693+ bottom_edge = self.main_window.get_bottom_edge()
694+ bottom_edge.open()
695+
696+ # open video resolution option value selector showing the possible
697+ # values
698+ video_resolution_button = (
699+ self.main_window.get_video_resolution_button())
700+ self.pointing_device.move_to_object(video_resolution_button)
701+ self.pointing_device.click()
702+ option_value_selector = self.main_window.get_option_value_selector()
703+ self.assertThat(
704+ option_value_selector.visible, Eventually(Equals(True)))
705+ optionButtons = option_value_selector.select_many("OptionValueButton")
706+ resolutions = [button.label for button in optionButtons if button.selected]
707+
708+ bottom_edge.close()
709+ return resolutions[0]
710+
711 def delete_all_videos(self):
712 video_files = os.listdir(self.videos_dir)
713 for f in video_files:
714
715=== modified file 'tests/autopilot/camera_app/tests/test_zoom.py'
716--- tests/autopilot/camera_app/tests/test_zoom.py 2015-04-29 15:56:44 +0000
717+++ tests/autopilot/camera_app/tests/test_zoom.py 2015-11-30 15:11:56 +0000
718@@ -68,3 +68,50 @@
719
720 self.pointing_device.drag(tx, ty, (tx - zoom_control.width), ty)
721 self.assertThat(zoom_control.value, Eventually(Equals(1.0)))
722+
723+ """Tests zoom is reset to minimum on camera switch"""
724+ def test_zoom_reset_on_camera_change(self):
725+ zoom_control = self.main_window.get_zoom_control()
726+ zoom_slider = self.main_window.get_zoom_slider()
727+
728+ self.activate_zoom()
729+ x, y, w, h = zoom_slider.globalRect
730+ tx = x + (w // 2)
731+ ty = y + (h // 2)
732+ self.pointing_device.drag(tx, ty, (tx + zoom_control.width), ty)
733+ self.assertThat(
734+ zoom_control.value, Eventually(Equals(zoom_control.maximumValue)))
735+
736+ self.main_window.switch_cameras()
737+ self.assertThat(
738+ zoom_control.value, Eventually(Equals(zoom_control.minimumValue)))
739+
740+ self.activate_zoom()
741+ self.pointing_device.drag(tx, ty, (tx + zoom_control.width), ty)
742+ self.assertThat(
743+ zoom_control.value, Eventually(Equals(zoom_control.maximumValue)))
744+
745+ self.main_window.switch_cameras()
746+ self.assertThat(
747+ zoom_control.value, Eventually(Equals(zoom_control.minimumValue)))
748+
749+ """Tests zoom is reset to minimum on recording mode switch"""
750+ def test_zoom_reset_on_recording_mode_change(self):
751+ zoom_control = self.main_window.get_zoom_control()
752+ zoom_slider = self.main_window.get_zoom_slider()
753+
754+ self.activate_zoom()
755+ x, y, w, h = zoom_slider.globalRect
756+ tx = x + (w // 2)
757+ ty = y + (h // 2)
758+ self.pointing_device.drag(tx, ty, (tx + zoom_control.width), ty)
759+ self.assertThat(
760+ zoom_control.value, Eventually(Equals(zoom_control.maximumValue)))
761+
762+ self.main_window.switch_recording_mode()
763+ self.assertThat(
764+ zoom_control.value, Eventually(Equals(zoom_control.minimumValue)))
765+
766+ # Ideally we should test the same thing when switching back to photo
767+ # mode, however due to http://pad.lv/1191088 zooming when recording
768+ # video is disabled, so adding that test is pointless until fixed.

Subscribers

People subscribed via source and target branches