diff --git a/src/contents/ui/CameraPage.qml b/src/contents/ui/CameraPage.qml index 51d404e..ee66157 100644 --- a/src/contents/ui/CameraPage.qml +++ b/src/contents/ui/CameraPage.qml @@ -1,278 +1,264 @@ /**************************************************************************** ** ** Copyright (C) 2018 Jonah Brüchert ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import QtQuick 2.7 import QtMultimedia 5.8 import org.kde.kirigami 2.0 as Kirigami import QtQuick.Controls 2.0 as Controls import QtQuick.Controls.Material 2.0 import QtQuick.Layouts 1.2 import QtGraphicalEffects 1.0 Kirigami.Page { id: cameraPage + property var camera + leftPadding: 0 rightPadding: 0 bottomPadding: 0 topPadding: 0 leftAction: Kirigami.Action { id: switchModeAction text: i18n("Switch mode") - icon.color: transparent + icon.color: "transparent" icon.name: { - if (camera.captureMode == Camera.CaptureStillImage) + if (camera.captureMode === Camera.CaptureStillImage) return "video-mp4" - else if (camera.captureMode == Camera.CaptureVideo) + else if (camera.captureMode === Camera.CaptureVideo) return "camera-photo-symbolic" } onTriggered: { - if (camera.captureMode == Camera.CaptureStillImage) + if (camera.captureMode === Camera.CaptureStillImage) camera.captureMode = Camera.CaptureVideo else camera.captureMode = Camera.CaptureStillImage console.log("Capture Mode switched") } } mainAction: Kirigami.Action { id: captureAction text: { - if (camera.captureMode == Camera.CaptureStillImage) + if (camera.captureMode === Camera.CaptureStillImage) return i18n("Capture photo") - else if (camera.videoRecorder.recorderStatus == CameraRecorder.RecordingStatus) + else if (camera.videoRecorder.recorderStatus === CameraRecorder.RecordingStatus) return i18n("Stop recording video") - else if (camera.captureMode == Camera.CaptureVideo) + else if (camera.captureMode === Camera.CaptureVideo) return i18n("Start recording video") } - iconName: { - if (camera.captureMode == Camera.CaptureStillImage) + icon.color: "transparent" + icon.name: { + if (camera.captureMode === Camera.CaptureStillImage) return "camera-photo" - else if (camera.videoRecorder.recorderStatus == CameraRecorder.RecordingStatus) + else if (camera.videoRecorder.recorderStatus === CameraRecorder.RecordingStatus) return "window-close" - else if (camera.captureMode == Camera.CaptureVideo) + else if (camera.captureMode === Camera.CaptureVideo) return "video-mp4" } onTriggered: { - if (camera.captureMode == Camera.CaptureStillImage) { + if (camera.captureMode === Camera.CaptureStillImage) { camera.imageCapture.capture() showPassiveNotification(i18n("Took a photo")) } - else if (camera.videoRecorder.recorderStatus == CameraRecorder.RecordingStatus) { + else if (camera.videoRecorder.recorderStatus === CameraRecorder.RecordingStatus) { camera.videoRecorder.stop() recordingFeedback.visible = false showPassiveNotification(i18n("Stopped recording")) } - else if (camera.captureMode == Camera.CaptureVideo) { + else if (camera.captureMode === Camera.CaptureVideo) { camera.videoRecorder.record() recordingFeedback.visible = true showPassiveNotification(i18n("Started recording")) } } } rightAction: Kirigami.Action { id: switchCameaAction text: i18n("Switch Camera") - iconName: "camera-photo" - enabled: (camera.position != "") + icon.color: "transparent" + icon.name: "camera-photo" + enabled: (camera.position !== Camera.UnspecifiedPosition) onTriggered: { if (settings.cameraPosition == Camera.BackFace) settings.cameraPosition = Camera.FrontFace else if (settings.cameraPosition == Camera.FrontFace) settings.cameraPosition = Camera.BackFace } } Rectangle { id: cameraUI state: "PhotoCapture" anchors { fill: parent centerIn: parent } color: "black" states: [ State { name: "PhotoCapture" StateChangeScript { script: { - camera.captureMode = Camera.CaptureStillImage - camera.start() + cameraPage.camera.captureMode = Camera.CaptureStillImage + cameraPage.camera.start() } } }, State { name: "VideoCapture" StateChangeScript { script: { - camera.captureMode = Camera.CaptureVideo - camera.start() + cameraPage.camera.captureMode = Camera.CaptureVideo + cameraPage.camera.start() } } } ] - Camera { - id: camera - captureMode: Camera.CaptureStillImage - deviceId: settings.cameraDeviceId - imageProcessing.whiteBalanceMode: settings.whiteBalanceMode - - imageCapture { - id: imageCapture - resolution: settings.resolution - } - - videoRecorder { - id: videoRecorder - resolution: settings.resolution - frameRate: 30 - } - } - VideoOutput { id: viewfinder visible: cameraUI.state == "PhotoCapture" || cameraUI.state == "VideoCapture" // Workaround orientation: Kirigami.Settings.isMobile ? -90 : 0 anchors.fill: parent - source: camera + source: cameraPage.camera } PinchArea { anchors.fill: parent property real initialZoom onPinchStarted: { - initialZoom = camera.digitalZoom; + initialZoom = cameraPage.camera.digitalZoom; } onPinchUpdated: { - var scale = camera.maximumDigitalZoom / 8 * pinch.scale - camera.maximumDigitalZoom / 8; - camera.setDigitalZoom(Math.min(camera.maximumDigitalZoom, camera.digitalZoom + scale)) + var scale = cameraPage.camera.maximumDigitalZoom / 8 * pinch.scale - cameraPage.camera.maximumDigitalZoom / 8; + cameraPage.camera.setDigitalZoom(Math.min(cameraPage.camera.maximumDigitalZoom, cameraPage.camera.digitalZoom + scale)) } } MouseArea { anchors.fill: parent onClicked: { - if (camera.lockStatus == Camera.Unlocked) { - camera.searchAndLock(); + if (cameraPage.camera.lockStatus === cameraPage.camera.Unlocked) { + cameraPage.camera.searchAndLock(); console.log("searching focus...") } else { - camera.unlock(); + cameraPage.camera.unlock(); console.log("unlocking focus...") } } } } ZoomControl { anchors { right: parent.right margins: Kirigami.Units.gridUnit * 2 } width : Kirigami.Units.gridUnit * 2 height: parent.height - currentZoom: camera.digitalZoom - maximumZoom: Math.min(4.0, camera.maximumDigitalZoom) - onZoomTo: camera.setDigitalZoom(value) + currentZoom: cameraPage.camera.digitalZoom + maximumZoom: Math.min(4.0, cameraPage.camera.maximumDigitalZoom) + onZoomTo: cameraPage.camera.setDigitalZoom(value) } Rectangle { id: recordingFeedback visible: false color: "red" radius: Kirigami.Units.gridUnit height: Kirigami.Units.gridUnit * 2 width: height layer.enabled: recordingFeedback.enabled layer.effect: DropShadow { color: Material.dropShadowColor samples: 30 spread: 0.5 } anchors { left: parent.left top: parent.top margins: Kirigami.Units.gridUnit * 2 } } Rectangle { id: preview visible: imageCapture.capturedImagePath width: Kirigami.Units.gridUnit * 6 height: width layer.enabled: preview.enabled layer.effect: DropShadow { color: Material.dropShadowColor samples: 30 spread: 0.5 } MouseArea { anchors.fill: parent onClicked: Qt.openUrlExternally("file://" + imageCapture.capturedImagePath) } anchors { right: parent.right bottom: parent.bottom margins: Kirigami.Units.gridUnit } Image { fillMode: Image.PreserveAspectCrop anchors.fill: parent source: "file://" + imageCapture.capturedImagePath } } } diff --git a/src/contents/ui/GlobalDrawer.qml b/src/contents/ui/GlobalDrawer.qml index 421d5eb..3444e21 100644 --- a/src/contents/ui/GlobalDrawer.qml +++ b/src/contents/ui/GlobalDrawer.qml @@ -1,151 +1,149 @@ /**************************************************************************** ** ** Copyright (C) 2018 Jonah Brüchert ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import org.kde.kirigami 2.0 as Kirigami import QtQuick 2.7 import QtMultimedia 5.8 Kirigami.GlobalDrawer { + id: drawer + property var camera + Component { id: devicesSubAction Kirigami.Action { property string value onTriggered: { settings.cameraDeviceId = value } } } Component { id: resolutionSubAction Kirigami.Action { property size value onTriggered: { settings.resolution = value } } } actions: [ Kirigami.Action { id: devicesAction text: i18n("Camera") iconName: "camera-photo" Component.onCompleted: { var cameras = QtMultimedia.availableCameras var childrenList = [] for (var i in cameras) { childrenList[i] = devicesSubAction.createObject(devicesAction, { value: cameras[i].deviceId, text: "%1".arg(cameras[i].displayName) }) devicesAction.children = childrenList } } }, Kirigami.Action { id: resolutionAction text: i18n("Resolution") iconName: "ratiocrop" Component.onCompleted: { - var resolutions = camera.imageCapture.supportedResolutions + var resolutions = drawer.camera.imageCapture.supportedResolutions var childrenList = [] for (var i in resolutions) { var pixels = resolutions[i].width * resolutions[i].height var megapixels = Math.round(pixels / 10000) / 100 childrenList[i] = resolutionSubAction.createObject(resolutionAction, { value: resolutions[i], text: "%1 x %2 (%3 MP)".arg(resolutions[i].width).arg(resolutions[i].height).arg(megapixels) }) resolutionAction.children = childrenList } } }, Kirigami.Action { id: wbaction text: i18n("White balance") iconName: "whitebalance" Kirigami.Action { iconName: "qrc:///camera_auto_mode.png" onTriggered: settings.whiteBalanceMode = CameraImageProcessing.WhiteBalanceAuto text: i18n("Auto") } Kirigami.Action { iconName: "qrc:///camera_white_balance_sunny.png" onTriggered: settings.whiteBalanceMode = CameraImageProcessing.WhiteBalanceSunlight text: i18n("Sunlight") } Kirigami.Action { iconName: "qrc:///camera_white_balance_cloudy.png" onTriggered: settings.whiteBalanceMode = CameraImageProcessing.WhiteBalanceCloudy text: i18n("Cloudy") } Kirigami.Action { iconName: "qrc:///camera_white_balance_incandescent.png" onTriggered: settings.whiteBalanceMode = CameraImageProcessing.WhiteBalanceTungsten text: i18n("Tungsten") } Kirigami.Action { iconName: "qrc:///camera_white_balance_flourescent.png" onTriggered: settings.whiteBalanceMode = CameraImageProcessing.WhiteBalanceFluorescent text: i18n("Fluorescent") } }, Kirigami.Action { text: i18n("About") iconName: "help-about" onTriggered: { aboutDialog.open(); } } ] - - Camera { - id: camera - deviceId: settings.cameraDeviceId - } } diff --git a/src/contents/ui/main.qml b/src/contents/ui/main.qml index 32d50bd..b3c4bf5 100644 --- a/src/contents/ui/main.qml +++ b/src/contents/ui/main.qml @@ -1,77 +1,103 @@ /**************************************************************************** ** ** Copyright (C) 2018 Jonah Brüchert ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ import QtQuick 2.7 import org.kde.kirigami 2.2 as Kirigami import Qt.labs.settings 1.0 import QtMultimedia 5.8 Kirigami.ApplicationWindow { id: root Settings { id: settings // Default settings property size resolution property string cameraDeviceId property int cameraPosition property int whiteBalanceMode } - Component {id: cameraPage; CameraPage {}} + Component { + id: cameraPage + + CameraPage { + camera: mainCamera + } + } // About Dialog AboutDialog { id: aboutDialog focus: true x: (parent.width - width) / 2 y: (parent.height - height) / 2 } + Camera { + id: mainCamera + captureMode: Camera.CaptureStillImage + deviceId: settings.cameraDeviceId + imageProcessing.whiteBalanceMode: settings.whiteBalanceMode + + imageCapture { + id: imageCapture + resolution: settings.resolution + } + + videoRecorder { + id: videoRecorder + resolution: settings.resolution + frameRate: 30 + } + } + title: i18n("Camera") - globalDrawer: GlobalDrawer {} + globalDrawer: GlobalDrawer { + camera: mainCamera + } pageStack.initialPage: cameraPage pageStack.globalToolBar.style: { if (Kirigami.Settings.isMobile) return Kirigami.ApplicationHeaderStyle.None else return Kirigami.ApplicationHeaderStyle.ToolBar } }