Warning, /utilities/krecorder/src/contents/ui/RecordPage.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  * SPDX-FileCopyrightText: 2020 Jonah BrĂ¼chert <jbb@kaidan.im>
0003  * SPDX-FileCopyrightText: 2020-2022 Devin Lin <espidev@gmail.com>
0004  *
0005  * SPDX-License-Identifier: GPL-3.0-or-later
0006  */
0007 
0008 import QtQuick
0009 import QtQuick.Controls as Controls
0010 import QtQuick.Layouts
0011 
0012 import org.kde.kirigami as Kirigami
0013 
0014 import KRecorder
0015 
0016 import "components"
0017 
0018 Kirigami.Page {
0019     id: root
0020     visible: false
0021     title: i18n("Record Audio")
0022 
0023     property bool isStopped: AudioRecorder.recorderState === AudioRecorder.StoppedState
0024     property bool isPaused: AudioRecorder.recorderState === AudioRecorder.PausedState
0025 
0026     onVisibleChanged: {
0027         // if page has been opened, and not in a recording session, start recording
0028         if (visible && (!isStopped && !isPaused)) {
0029             AudioRecorder.record();
0030         }
0031     }
0032     
0033     Connections {
0034         target: AudioRecorder
0035         function onErrorChanged() {
0036             console.warn("Error on the recorder", AudioRecorder.errorString)
0037         }
0038     }
0039     
0040     ColumnLayout {
0041         id: column
0042         anchors.fill: parent
0043         
0044         Controls.Label {
0045             id: timeText
0046             Layout.alignment: Qt.AlignHCenter
0047             Layout.bottomMargin: Kirigami.Units.largeSpacing
0048             text: isStopped ? "00:00:00" : Utils.formatTime(AudioRecorder.duration)
0049             opacity: (root.isStopped || root.isPaused) ? 0.5 : 0.7
0050             font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize * 3)
0051             font.weight: Font.DemiBold
0052         }
0053         
0054         Item { Layout.fillHeight: true }
0055         
0056         // TODO visualization disabled until we port the model to Qt6
0057         // Visualization {
0058         //     Layout.fillWidth: true
0059             
0060         //     prober: AudioRecorder.prober
0061         //     showBarsFromMiddle: true
0062         //     showLine: true
0063         //     height: Kirigami.Units.gridUnit * 10
0064         //     maxBarHeight: Kirigami.Units.gridUnit * 5 * 2
0065         //     animationIndex: AudioRecorder.prober.animationIndex
0066             
0067         //     volumes: AudioRecorder.prober.volumesList
0068         // }
0069         
0070         // placeholder visualization for now
0071         Item {
0072             id: visualization
0073             height: Kirigami.Units.gridUnit * 10
0074             Layout.fillWidth: true
0075 
0076             Rectangle {
0077                 color: Kirigami.Theme.highlightColor
0078                 anchors.centerIn: parent
0079                 height: Kirigami.Units.gridUnit * 12
0080                 width: height
0081                 radius: height / 2
0082                 opacity: 0.5
0083                 transformOrigin: Item.Center
0084                 scale: stopAnim.min
0085 
0086                 NumberAnimation on scale {
0087                     id: recordingAnim
0088                     property real min: (9 / 12)
0089                     property real max: 1.0
0090                     to: max
0091                     running: !root.isStopped && !root.isPaused
0092                     easing.type: Easing.OutBack
0093                     duration: 2000
0094                     onRunningChanged: Easing.OutBack
0095 
0096                     onFinished: {
0097                         to = (to === min) ? max : min;
0098                         easing.type = (to === min) ? Easing.InBack : Easing.OutBack;
0099                         restart();
0100                     }
0101                 }
0102 
0103                 NumberAnimation on scale {
0104                     id: stopAnim
0105                     to: (7 / 12)
0106                     running: root.isStopped || root.isPaused
0107                     easing.type: Easing.OutExpo
0108                     duration: 2000
0109                 }
0110             }
0111 
0112             RoundFlatButton {
0113                 id: pauseButton
0114                 anchors.centerIn: parent
0115                 height: Kirigami.Units.gridUnit * 7
0116                 width: height
0117                 text: (!isStopped && isPaused) ? i18n("Continue") : i18n("Pause")
0118                 
0119                 onClicked: {
0120                     if (isPaused) {
0121                         AudioRecorder.record();
0122                     } else {
0123                         AudioRecorder.pause();
0124                     }
0125                 }
0126             }
0127 
0128             ColumnLayout {
0129                 anchors.centerIn: parent
0130                 Kirigami.Theme.inherit: false
0131                 Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
0132 
0133                 Kirigami.Icon {
0134                     source: 'microphone-sensitivity-high'
0135                     implicitHeight: Kirigami.Units.iconSizes.huge
0136                     implicitWidth: Kirigami.Units.iconSizes.huge
0137                 }
0138                 Controls.Label {
0139                     visible: isStopped || isPaused
0140                     Layout.alignment: Qt.AlignCenter
0141                     text: i18n('Paused')
0142                     font.bold: true
0143                 }
0144             }
0145         }
0146 
0147         Item { Layout.fillHeight: true }
0148         
0149         RowLayout {
0150             spacing: Math.round(Kirigami.Units.gridUnit * 1.5)
0151             
0152             Layout.fillWidth: true
0153             Layout.bottomMargin: Kirigami.Units.gridUnit
0154             Layout.topMargin: Kirigami.Units.largeSpacing
0155             
0156             Item { Layout.fillWidth: true }
0157             
0158             // moved pause button until we port the visualization to Qt6
0159             // ToolTipToolButton {
0160             //     implicitWidth: Math.round(Kirigami.Units.gridUnit * 2.5)
0161             //     implicitHeight: Math.round(Kirigami.Units.gridUnit * 2.5)
0162             //     text: (!isStopped && isPaused) ? i18n("Continue") : i18n("Pause")
0163             //     icon.name: (!isStopped && isPaused) ? "media-playback-start" : "media-playback-pause"
0164                 
0165             //     onClicked: {
0166             //         if (isPaused) {
0167             //             AudioRecorder.record();
0168             //         } else {
0169             //             AudioRecorder.pause();
0170             //         }
0171             //     }
0172             // }
0173             
0174             RoundFlatButton {
0175                 id: stopButton
0176                 text: i18n("Save Recording")
0177                 
0178                 icon.name: "checkmark"
0179                 
0180                 onClicked: {
0181                     // pop record page off
0182                     applicationWindow().pageStack.layers.pop();
0183                     
0184                     // save recording
0185                     recordingName.text = RecordingModel.nextDefaultRecordingName();
0186                     saveDialog.open();
0187                     AudioRecorder.pause();
0188                 }
0189             }
0190 
0191             ToolTipToolButton {
0192                 implicitWidth: Math.round(Kirigami.Units.gridUnit * 2.5)
0193                 implicitHeight: Math.round(Kirigami.Units.gridUnit * 2.5)
0194                 text: i18n("Delete")
0195                 icon.name: "delete"
0196                 
0197                 onClicked: {
0198                     // pop record page off
0199                     applicationWindow().pageStack.layers.pop();
0200                     AudioRecorder.reset();
0201                 }
0202             }
0203             
0204             Item { Layout.fillWidth: true }
0205         }
0206     }
0207     
0208     Kirigami.Dialog {
0209         id: saveDialog
0210         standardButtons: Kirigami.Dialog.NoButton
0211         padding: Kirigami.Units.largeSpacing
0212         bottomPadding: Kirigami.Units.largeSpacing + Kirigami.Units.smallSpacing
0213         
0214         title: i18n("Save recording")
0215         
0216         customFooterActions: [
0217             Kirigami.Action {
0218                 text: i18n("Save")
0219                 icon.name: "document-save"
0220                 onTriggered: {
0221                     AudioRecorder.setRecordingName(recordingName.text);
0222                     AudioRecorder.stop();
0223                     pageStack.layers.pop();
0224                     recordingName.text = "";
0225                             
0226                     saveDialog.close();
0227                 }
0228             },
0229             Kirigami.Action {
0230                 text: i18n("Discard")
0231                 icon.name: "delete"
0232                 onTriggered: {
0233                     AudioRecorder.reset()
0234                     saveDialog.close();
0235                 }
0236             }
0237         ]
0238         
0239         Kirigami.FormLayout {
0240             implicitWidth: Kirigami.Units.gridUnit * 20
0241             
0242             Controls.TextField {
0243                 id: recordingName
0244                 Kirigami.FormData.label: i18n("Name:")
0245                 placeholderText: i18n("Name (optional)")
0246             }
0247             
0248             Controls.Label {
0249                 Kirigami.FormData.label: i18n("Storage Folder:")
0250                 Layout.fillWidth: true
0251                 wrapMode: Text.Wrap
0252                 text: AudioRecorder.storageFolder
0253             }
0254         }
0255     }
0256 }