From 6fa6ebef77372d49315d3f040f9a869e08130318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pekka=20Geh=C3=B6r?= Date: Wed, 17 Nov 2021 16:43:00 +0200 Subject: Declarative-camera facelift for mobile After patch, you can use the camera in portrait and landscape mode on mobile devices. Task-number: QTBUG-96077 Change-Id: Idd46498e1166bab09a27d182ce707d8bb4528c24 Reviewed-by: Lars Knoll Reviewed-by: Assam Boudjelthia (cherry picked from commit 0ebbcc10f122d56baee5d2519eb6e99d47af68ab) --- .../declarative-camera/CameraListButton.qml | 28 +++- .../declarative-camera/CameraPropertyButton.qml | 29 +++- .../declarative-camera/PhotoCaptureControls.qml | 157 ++++++++++++++---- .../declarative-camera/VideoCaptureControls.qml | 182 ++++++++++++++++----- .../declarative-camera/declarative-camera.qml | 46 +++++- 5 files changed, 358 insertions(+), 84 deletions(-) diff --git a/examples/multimedia/declarative-camera/CameraListButton.qml b/examples/multimedia/declarative-camera/CameraListButton.qml index 3a47479eb..2b2716eb7 100644 --- a/examples/multimedia/declarative-camera/CameraListButton.qml +++ b/examples/multimedia/declarative-camera/CameraListButton.qml @@ -75,9 +75,7 @@ Item { CameraListPopup { id: popup - anchors.right: parent.left anchors.rightMargin: 16 - anchors.top: parent.top visible: opacity > 0 model: mediaDevices.videoInputs @@ -87,4 +85,30 @@ Item { onSelected: popup.toggle() } + + states: [ + State { + name: "MobilePortrait" + AnchorChanges { + target: popup + anchors.bottom: parent.top; + } + }, + State { + name: "MobileLandscape" + AnchorChanges { + target: popup + anchors.top: parent.top; + anchors.right: parent.left; + } + }, + State { + name: "Other" + AnchorChanges { + target: popup + anchors.top: parent.top; + anchors.right: parent.left; + } + } + ] } diff --git a/examples/multimedia/declarative-camera/CameraPropertyButton.qml b/examples/multimedia/declarative-camera/CameraPropertyButton.qml index cf77f95f0..91961ebf0 100644 --- a/examples/multimedia/declarative-camera/CameraPropertyButton.qml +++ b/examples/multimedia/declarative-camera/CameraPropertyButton.qml @@ -77,14 +77,37 @@ Item { CameraPropertyPopup { id: popup - anchors.right: parent.left anchors.rightMargin: 16 - anchors.top: parent.top visible: opacity > 0 currentValue: propertyButton.value onSelected: popup.toggle() } -} + states: [ + State { + name: "MobilePortrait" + AnchorChanges { + target: popup + anchors.bottom: parent.top; + } + }, + State { + name: "MobileLandscape" + AnchorChanges { + target: popup + anchors.verticalCenter: parent.top; + anchors.right: parent.left; + } + }, + State { + name: "Other" + AnchorChanges { + target: popup + anchors.top: parent.top; + anchors.right: parent.left; + } + } + ] +} diff --git a/examples/multimedia/declarative-camera/PhotoCaptureControls.qml b/examples/multimedia/declarative-camera/PhotoCaptureControls.qml index c5ac09415..0f2745665 100644 --- a/examples/multimedia/declarative-camera/PhotoCaptureControls.qml +++ b/examples/multimedia/declarative-camera/PhotoCaptureControls.qml @@ -50,43 +50,41 @@ import QtQuick import QtMultimedia +import QtQuick.Layouts FocusScope { + id : captureControls property CaptureSession captureSession property bool previewAvailable : false - property int buttonsPanelWidth: buttonPaneShadow.width + property int buttonsmargin: 8 + property int buttonsPanelWidth + property int buttonsPanelPortraitHeight + property int buttonsWidth signal previewSelected signal videoModeSelected - id : captureControls Rectangle { id: buttonPaneShadow - width: bottomColumn.width + 16 - height: parent.height - anchors.top: parent.top - anchors.right: parent.right color: Qt.rgba(0.08, 0.08, 0.08, 1) - Column { - anchors { - right: parent.right - top: parent.top - margins: 8 - } - + GridLayout { id: buttonsColumn - spacing: 8 - + anchors.margins: buttonsmargin + flow: captureControls.state === "MobilePortrait" + ? GridLayout.LeftToRight : GridLayout.TopToBottom CameraButton { text: "Capture" + implicitWidth: buttonsWidth visible: captureSession.imageCapture.readyForCapture onClicked: captureSession.imageCapture.captureToFile("") } CameraPropertyButton { id : wbModesButton + implicitWidth: buttonsWidth + state: captureControls.state value: Camera.WhiteBalanceAuto model: ListModel { ListElement { @@ -118,46 +116,48 @@ FocusScope { onValueChanged: captureControls.captureSession.camera.whiteBalanceMode = wbModesButton.value } - CameraButton { - text: "View" - onClicked: captureControls.previewSelected() - visible: captureControls.previewAvailable + Item { + implicitWidth: buttonsWidth + height: 70 + CameraButton { + text: "View" + anchors.fill: parent + onClicked:state = captureControls.previewSelected() + visible: captureControls.previewAvailable + } } } - Column { - anchors { - bottom: parent.bottom - right: parent.right - margins: 8 - } - + GridLayout { id: bottomColumn - spacing: 8 + anchors.margins: buttonsmargin + flow: captureControls.state === "MobilePortrait" + ? GridLayout.LeftToRight : GridLayout.TopToBottom CameraListButton { + implicitWidth: buttonsWidth + state: captureControls.state onValueChanged: captureSession.camera.cameraDevice = value } CameraButton { text: "Switch to Video" + implicitWidth: buttonsWidth onClicked: captureControls.videoModeSelected() } CameraButton { id: quitButton + implicitWidth: buttonsWidth text: "Quit" onClicked: Qt.quit() } } - - } - ZoomControl { x : 0 - y : 0 + y : captureControls.state === "MobilePortrait" ? -buttonPaneShadow.height : 0 width : 100 height: parent.height @@ -165,4 +165,99 @@ FocusScope { maximumZoom: camera.maximumZoomFactor onZoomTo: camera.setDigitalZoom(value) } + + states: [ + State { + name: "MobilePortrait" + PropertyChanges { + target: buttonPaneShadow + width: parent.width + height: captureControls.buttonsPanelPortraitHeight + } + PropertyChanges { + target: buttonsColumn + height: captureControls.buttonsPanelPortraitHeight / 2 - buttonsmargin + } + PropertyChanges { + target: bottomColumn + height: captureControls.buttonsPanelPortraitHeight / 2 - buttonsmargin + } + AnchorChanges { + target: buttonPaneShadow + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + } + AnchorChanges { + target: buttonsColumn + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + } + AnchorChanges { + target: bottomColumn + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + } + }, + State { + name: "MobileLandscape" + PropertyChanges { + target: buttonPaneShadow + width: buttonsPanelWidth + height: parent.height + } + PropertyChanges { + target: buttonsColumn + height: parent.height + width: buttonPaneShadow.width / 2 + } + PropertyChanges { + target: bottomColumn + height: parent.height + width: buttonPaneShadow.width / 2 + } + AnchorChanges { + target: buttonPaneShadow + anchors.top: parent.top + anchors.right: parent.right + } + AnchorChanges { + target: buttonsColumn + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + } + AnchorChanges { + target: bottomColumn + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + } + }, + State { + name: "Other" + PropertyChanges { + target: buttonPaneShadow + width: bottomColumn.width + 16 + height: parent.height + } + AnchorChanges { + target: buttonPaneShadow + anchors.top: parent.top + anchors.right: parent.right + } + AnchorChanges { + target: buttonsColumn + anchors.top: parent.top + anchors.right: parent.right + } + AnchorChanges { + target: bottomColumn + anchors.bottom: parent.bottom + anchors.right: parent.right + } + } + ] } diff --git a/examples/multimedia/declarative-camera/VideoCaptureControls.qml b/examples/multimedia/declarative-camera/VideoCaptureControls.qml index 7b8d19531..53682f88b 100644 --- a/examples/multimedia/declarative-camera/VideoCaptureControls.qml +++ b/examples/multimedia/declarative-camera/VideoCaptureControls.qml @@ -50,87 +50,96 @@ import QtQuick import QtMultimedia +import QtQuick.Layouts FocusScope { + id : captureControls property CaptureSession captureSession property bool previewAvailable : false - property int buttonsPanelWidth: buttonPaneShadow.width + property int buttonsmargin: 8 + property int buttonsPanelWidth + property int buttonsPanelPortraitHeight + property int buttonsWidth signal previewSelected signal photoModeSelected - id : captureControls Rectangle { id: buttonPaneShadow - width: bottomColumn.width + 16 - height: parent.height - anchors.top: parent.top - anchors.right: parent.right color: Qt.rgba(0.08, 0.08, 0.08, 1) - Column { - anchors { - right: parent.right - top: parent.top - margins: 8 - } - + GridLayout { id: buttonsColumn - spacing: 8 - - CameraButton { - text: "Record" - visible: captureSession.recorder.status !== MediaRecorder.RecordingStatus - onClicked: captureSession.recorder.record() + anchors.margins: buttonsmargin + flow: captureControls.state === "MobilePortrait" + ? GridLayout.LeftToRight : GridLayout.TopToBottom + Item { + implicitWidth: buttonsWidth + height: 70 + CameraButton { + text: "Record" + anchors.fill: parent + visible: captureSession.recorder.status !== MediaRecorder.RecordingStatus + onClicked: captureSession.recorder.record() + } } - CameraButton { - id: stopButton - text: "Stop" - visible: captureSession.recorder.status === MediaRecorder.RecordingStatus - onClicked: captureSession.recorder.stop() + Item { + implicitWidth: buttonsWidth + height: 70 + CameraButton { + id: stopButton + text: "Stop" + anchors.fill: parent + visible: captureSession.recorder.status === MediaRecorder.RecordingStatus + onClicked: captureSession.recorder.stop() + } } - CameraButton { - text: "View" - onClicked: captureControls.previewSelected() - //don't show View button during recording - visible: captureSession.recorder.actualLocation && !stopButton.visible + Item { + implicitWidth: buttonsWidth + height: 70 + CameraButton { + text: "View" + anchors.fill: parent + onClicked: captureControls.previewSelected() + //don't show View button during recording + visible: captureSession.recorder.actualLocation && !stopButton.visible + } } } - Column { - anchors { - bottom: parent.bottom - right: parent.right - margins: 8 - } - + GridLayout { id: bottomColumn - spacing: 8 + anchors.margins: buttonsmargin + flow: captureControls.state === "MobilePortrait" + ? GridLayout.LeftToRight : GridLayout.TopToBottom CameraListButton { + implicitWidth: buttonsWidth onValueChanged: captureSession.camera.cameraDevice = value + state: captureControls.state } CameraButton { text: "Switch to Photo" + implicitWidth: buttonsWidth onClicked: captureControls.photoModeSelected() } CameraButton { id: quitButton text: "Quit" + implicitWidth: buttonsWidth onClicked: Qt.quit() } } } - ZoomControl { x : 0 - y : 0 + y : captureControls.state === "MobilePortrait" ? -buttonPaneShadow.height : 0 width : 100 height: parent.height @@ -138,4 +147,99 @@ FocusScope { maximumZoom: captureSession.camera.maximumZoomFactor onZoomTo: captureSession.camera.zoomFactor = value } + + states: [ + State { + name: "MobilePortrait" + PropertyChanges { + target: buttonPaneShadow + width: parent.width + height: buttonsPanelPortraitHeight + } + PropertyChanges { + target: buttonsColumn + height: captureControls.buttonsPanelPortraitHeight / 2 - buttonsmargin + } + PropertyChanges { + target: bottomColumn + height: captureControls.buttonsPanelPortraitHeight / 2 - buttonsmargin + } + AnchorChanges { + target: buttonPaneShadow + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + } + AnchorChanges { + target: buttonsColumn + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + } + AnchorChanges { + target: bottomColumn; + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + } + }, + State { + name: "MobileLandscape" + PropertyChanges { + target: buttonPaneShadow + width: buttonsPanelWidth + height: parent.height + } + PropertyChanges { + target: buttonsColumn + height: parent.height + width: buttonPaneShadow.width / 2 + } + PropertyChanges { + target: bottomColumn + height: parent.height + width: buttonPaneShadow.width / 2 + } + AnchorChanges { + target: buttonPaneShadow + anchors.top: parent.top + anchors.right: parent.right + } + AnchorChanges { + target: buttonsColumn; + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left; + } + AnchorChanges { + target: bottomColumn; + anchors.top: parent.top; + anchors.bottom: parent.bottom; + anchors.right: parent.right; + } + }, + State { + name: "Other" + PropertyChanges { + target: buttonPaneShadow; + width: bottomColumn.width + 16; + height: parent.height; + } + AnchorChanges { + target: buttonPaneShadow; + anchors.top: parent.top; + anchors.right: parent.right; + } + AnchorChanges { + target: buttonsColumn; + anchors.top: parent.top + anchors.right: parent.right + } + AnchorChanges { + target: bottomColumn; + anchors.bottom: parent.bottom; + anchors.right: parent.right; + } + } + ] } diff --git a/examples/multimedia/declarative-camera/declarative-camera.qml b/examples/multimedia/declarative-camera/declarative-camera.qml index 51efb2b5b..6260c4281 100644 --- a/examples/multimedia/declarative-camera/declarative-camera.qml +++ b/examples/multimedia/declarative-camera/declarative-camera.qml @@ -56,10 +56,31 @@ Rectangle { width: 800 height: 480 - color: "black" state: "PhotoCapture" + property string platformScreen: "" + property int buttonsPanelLandscapeWidth: 328 + property int buttonsPanelPortraitHeight: 180 + + onWidthChanged: { + setState() + } + function setState() { + if (Qt.platform.os === "android" || Qt.platform.os === "ios") { + if (Screen.desktopAvailableWidth < Screen.desktopAvailableHeight) { + stillControls.state = "MobilePortrait"; + } else { + stillControls.state = "MobileLandscape"; + } + } else { + stillControls.state = "Other"; + } + console.log("State: " + stillControls.state); + stillControls.buttonsWidth = (stillControls.state === "MobilePortrait") + ? Screen.desktopAvailableWidth/3.4 : 144 + } + states: [ State { name: "PhotoCapture" @@ -111,7 +132,7 @@ Rectangle { id : photoPreview anchors.fill : parent onClosed: cameraUI.state = "PhotoCapture" - visible: cameraUI.state == "PhotoPreview" + visible: (cameraUI.state === "PhotoPreview") focus: visible source: imageCapture.preview } @@ -120,7 +141,7 @@ Rectangle { id : videoPreview anchors.fill : parent onClosed: cameraUI.state = "VideoCapture" - visible: cameraUI.state == "VideoPreview" + visible: (cameraUI.state === "VideoPreview") focus: visible //don't load recorded video if preview is invisible @@ -129,20 +150,23 @@ Rectangle { VideoOutput { id: viewfinder - visible: cameraUI.state == "PhotoCapture" || cameraUI.state == "VideoCapture" + visible: ((cameraUI.state === "PhotoCapture") || (cameraUI.state === "VideoCapture")) x: 0 y: 0 - width: parent.width - stillControls.buttonsPanelWidth - height: parent.height -// autoOrientation: true + width: ((stillControls.state === "MobilePortrait") ? parent.width : (parent.width-buttonsPanelLandscapeWidth)) + height: ((stillControls.state === "MobilePortrait") ? parent.height - buttonsPanelPortraitHeight : parent.height) + // autoOrientation: true } PhotoCaptureControls { id: stillControls + state: setState() anchors.fill: parent + buttonsPanelPortraitHeight: cameraUI.buttonsPanelPortraitHeight + buttonsPanelWidth: cameraUI.buttonsPanelLandscapeWidth captureSession: captureSession - visible: cameraUI.state == "PhotoCapture" + visible: (cameraUI.state === "PhotoCapture") onPreviewSelected: cameraUI.state = "PhotoPreview" onVideoModeSelected: cameraUI.state = "VideoCapture" previewAvailable: imageCapture.preview.length !== 0 @@ -150,9 +174,13 @@ Rectangle { VideoCaptureControls { id: videoControls + state: stillControls.state anchors.fill: parent + buttonsWidth: stillControls.buttonsWidth + buttonsPanelPortraitHeight: cameraUI.buttonsPanelPortraitHeight + buttonsPanelWidth: cameraUI.buttonsPanelLandscapeWidth captureSession: captureSession - visible: cameraUI.state == "VideoCapture" + visible: (cameraUI.state === "VideoCapture") onPreviewSelected: cameraUI.state = "VideoPreview" onPhotoModeSelected: cameraUI.state = "PhotoCapture" } -- cgit v1.2.3