mirror of https://github.com/KDE/kasts.git
Implement custom playback rate selection
Also refactor playbackrate dialog and store values in settings Solves #12
This commit is contained in:
parent
c5d89f01d4
commit
bbc8562100
|
@ -147,12 +147,21 @@ FocusScope {
|
|||
Controls.ToolTip.text: i18n("Skip Forward")
|
||||
}
|
||||
Controls.ToolButton {
|
||||
id: playbackRateButton
|
||||
contentItem: Controls.Label {
|
||||
text: AudioManager.playbackRate + "x"
|
||||
text: AudioManager.playbackRate.toFixed(2) + "x"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
onClicked: playbackRateDialog.open()
|
||||
checkable: true
|
||||
checked: playbackRateMenu.visible
|
||||
onClicked: {
|
||||
if (playbackRateMenu.visible) {
|
||||
playbackRateMenu.dismiss();
|
||||
} else {
|
||||
playbackRateMenu.popup(playbackRateButton, 0, playbackRateButton.height);
|
||||
}
|
||||
}
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
padding: 0
|
||||
implicitWidth: playButton.width * 1.5
|
||||
|
@ -160,7 +169,7 @@ FocusScope {
|
|||
|
||||
Controls.ToolTip.visible: hovered
|
||||
Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
Controls.ToolTip.text: i18n("Playback Rate: ") + AudioManager.playbackRate + "x"
|
||||
Controls.ToolTip.text: i18n("Playback Rate: ") + AudioManager.playbackRate.toFixed(2) + "x"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,4 +454,9 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlaybackRateMenu {
|
||||
id: playbackRateMenu
|
||||
parentButton: playbackRateButton
|
||||
}
|
||||
}
|
||||
|
|
|
@ -464,15 +464,22 @@ Kirigami.Page {
|
|||
|
||||
// left section
|
||||
Controls.Button {
|
||||
id: playbackRateButton
|
||||
// Use contentItem and a Label because using plain "text"
|
||||
// does not rescale automatically if the text changes
|
||||
contentItem: Controls.Label {
|
||||
text: AudioManager.playbackRate + "x"
|
||||
text: AudioManager.playbackRate.toFixed(2) + "x"
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
checkable: true
|
||||
checked: playbackRateMenu.visible
|
||||
onClicked: {
|
||||
playbackRateDialog.open()
|
||||
if (playbackRateMenu.visible) {
|
||||
playbackRateMenu.dismiss();
|
||||
} else {
|
||||
playbackRateMenu.popup(playbackRateButton, 0, -playbackRateMenu.height);
|
||||
}
|
||||
}
|
||||
flat: true
|
||||
padding: 0
|
||||
|
@ -532,4 +539,9 @@ Kirigami.Page {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlaybackRateMenu {
|
||||
id: playbackRateMenu
|
||||
parentButton: playbackRateButton
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2023 Bart De Vries <bart@mogwai.be>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14 as Controls
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import org.kde.kirigami 2.19 as Kirigami
|
||||
import org.kde.kasts 1.0
|
||||
|
||||
Kirigami.Dialog {
|
||||
id: customizeRatesDialog
|
||||
title: i18nc("@title:window", "Playback Rate Presets")
|
||||
padding: Kirigami.Units.largeSpacing
|
||||
preferredWidth: Kirigami.Units.gridUnit * 16 + Kirigami.Units.smallSpacing
|
||||
|
||||
closePolicy: Controls.Popup.CloseOnEscape
|
||||
standardButtons: Kirigami.Dialog.Save | Kirigami.Dialog.Cancel
|
||||
|
||||
ListModel {
|
||||
id: rateModel
|
||||
|
||||
Component.onCompleted: {
|
||||
for (var rate in SettingsManager.playbackRates) {
|
||||
rateModel.append({"value": SettingsManager.playbackRates[rate] / 100.0,
|
||||
"name": (SettingsManager.playbackRates[rate] / 100.0).toFixed(2) + "x"});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getRateList() {
|
||||
var list = [];
|
||||
for (var i = 0; i < rateModel.count; i++) {
|
||||
list.push(Math.round(rateModel.get(i).value * 100));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: playbackRateList
|
||||
|
||||
implicitWidth: customizeRatesDialog.width
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Controls.Label {
|
||||
Layout.fillWidth: true
|
||||
text: i18nc("@info Label for controls to add new playback rate preset", "New Preset:")
|
||||
}
|
||||
|
||||
Kirigami.Chip {
|
||||
text: (Math.round(rateSlider.value * 20) / 20.0).toFixed(2)
|
||||
closable: false
|
||||
checkable: false
|
||||
}
|
||||
|
||||
Controls.Button {
|
||||
id: addButton
|
||||
icon.name: "list-add"
|
||||
text: i18nc("@action:button Add new playback rate value to list", "Add")
|
||||
Controls.ToolTip.visible: hovered
|
||||
Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
Controls.ToolTip.text: i18nc("@info:tooltip", "Add new playback rate value to list")
|
||||
onClicked: {
|
||||
var found = false;
|
||||
var insertIndex = 0;
|
||||
var newValue = (Math.round(rateSlider.value * 20) / 20.0);
|
||||
for (var i = 0; i < rateModel.count; i++) {
|
||||
if (newValue == rateModel.get(i).value) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (newValue > rateModel.get(i).value) {
|
||||
insertIndex = i + 1;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
rateModel.insert(insertIndex, {"value": newValue,
|
||||
"name": newValue.toFixed(2) + "x"});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: Kirigami.Units.gridUnit
|
||||
|
||||
Controls.Button {
|
||||
text: "-"
|
||||
implicitWidth: addButton.height
|
||||
implicitHeight: addButton.height
|
||||
onClicked: rateSlider.value = Math.max(0.0, rateSlider.value - 0.05)
|
||||
Controls.ToolTip.visible: hovered
|
||||
Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
Controls.ToolTip.text: i18nc("@action:button", "Decrease Playback Rate")
|
||||
}
|
||||
|
||||
Controls.Slider {
|
||||
id: rateSlider
|
||||
Layout.fillWidth: true
|
||||
from: 0
|
||||
to: 3
|
||||
value: 1
|
||||
handle.implicitWidth: implicitHeight // workaround to make slider handle position itself exactly at the location of the click
|
||||
}
|
||||
|
||||
Controls.Button {
|
||||
text: "+"
|
||||
implicitWidth: addButton.height
|
||||
implicitHeight: addButton.height
|
||||
onClicked: rateSlider.value = Math.min(3.0, rateSlider.value + 0.05)
|
||||
Controls.ToolTip.visible: hovered
|
||||
Controls.ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
|
||||
Controls.ToolTip.text: i18nc("@action:button", "Increase Playback Rate")
|
||||
}
|
||||
}
|
||||
|
||||
Controls.Label {
|
||||
text: i18nc("@title:group List of custom playback rates", "Current Presets:")
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 4
|
||||
Layout.fillWidth: true
|
||||
Repeater {
|
||||
model: rateModel
|
||||
delegate: Kirigami.Chip {
|
||||
Layout.fillWidth: true
|
||||
text: model.value.toFixed(2)
|
||||
closable: true
|
||||
onRemoved: {
|
||||
for (var i = 0; i < rateModel.count; i++) {
|
||||
if (model.value == rateModel.get(i).value) {
|
||||
rateModel.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Swapnil Tripathi <swapnil06.st@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2023 Bart De Vries <bart@mogwai.be>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14 as Controls
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import org.kde.kirigami 2.19 as Kirigami
|
||||
import org.kde.kasts 1.0
|
||||
|
||||
Loader {
|
||||
sourceComponent: !Kirigami.Settings.isMobile ? widescreenComponent : narrowComponent
|
||||
|
||||
function open() {
|
||||
item.open();
|
||||
}
|
||||
ListModel {
|
||||
id: playbackRateModel
|
||||
ListElement {
|
||||
name: "0.50x"
|
||||
value: 0.50
|
||||
}
|
||||
ListElement {
|
||||
name: "0.75x"
|
||||
value: 0.75
|
||||
}
|
||||
ListElement {
|
||||
name: "1x"
|
||||
value: 1
|
||||
}
|
||||
ListElement {
|
||||
name: "1.25x"
|
||||
value: 1.25
|
||||
}
|
||||
ListElement {
|
||||
name: "1.50x"
|
||||
value: 1.50
|
||||
}
|
||||
ListElement {
|
||||
name: "1.75x"
|
||||
value: 1.75
|
||||
}
|
||||
ListElement {
|
||||
name: "2x"
|
||||
value: 2
|
||||
}
|
||||
ListElement {
|
||||
name: "2.25x"
|
||||
value: 2.25
|
||||
}
|
||||
ListElement {
|
||||
name: "2.5x"
|
||||
value: 2.5
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: widescreenComponent
|
||||
Kirigami.Dialog {
|
||||
id: listViewSheet
|
||||
title: i18n("Set Playback Rate")
|
||||
padding: 0
|
||||
preferredWidth: Kirigami.Units.gridUnit * 16
|
||||
|
||||
ColumnLayout {
|
||||
id: playbackRateList
|
||||
spacing: 0
|
||||
|
||||
Repeater {
|
||||
model: playbackRateModel
|
||||
delegate: Controls.RadioDelegate {
|
||||
id: swipeDelegate
|
||||
|
||||
Layout.fillWidth: true
|
||||
topPadding: Kirigami.Units.smallSpacing * 2
|
||||
bottomPadding: Kirigami.Units.smallSpacing * 2
|
||||
|
||||
text: name
|
||||
checked: value == AudioManager.playbackRate
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
AudioManager.playbackRate = value;
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: narrowComponent
|
||||
Kirigami.OverlayDrawer {
|
||||
id: drawer
|
||||
height: parent.height / 2
|
||||
edge: Qt.BottomEdge
|
||||
z: -1
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation { duration: Kirigami.Units.shortDuration }
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
id: contents
|
||||
spacing: 0
|
||||
|
||||
Kirigami.Heading {
|
||||
level: 3
|
||||
text: i18n("Set Playback Rate")
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.bottomMargin: Kirigami.Units.largeSpacing * 2
|
||||
}
|
||||
ListView {
|
||||
id: playbackRateList
|
||||
model: playbackRateModel
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
delegate: Kirigami.BasicListItem {
|
||||
highlighted: value == AudioManager.playbackRate
|
||||
label: model.name
|
||||
onClicked: {
|
||||
AudioManager.playbackRate = value;
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2023 Bart De Vries <bart@mogwai.be>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14 as Controls
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import org.kde.kirigami 2.19 as Kirigami
|
||||
import org.kde.kasts 1.0
|
||||
|
||||
Controls.Menu {
|
||||
id: playbackRateMenu
|
||||
|
||||
required property QtObject parentButton
|
||||
|
||||
title: i18nc("@title:window", "Select Playback Rate")
|
||||
|
||||
Controls.ButtonGroup { id: playbackRateGroup }
|
||||
|
||||
ColumnLayout {
|
||||
Repeater {
|
||||
model: playbackRateModel
|
||||
|
||||
Controls.RadioButton {
|
||||
padding: Kirigami.Units.smallSpacing
|
||||
text: model.value
|
||||
checked: model.value === AudioManager.playbackRate.toFixed(2)
|
||||
Controls.ButtonGroup.group: playbackRateGroup
|
||||
|
||||
onToggled: {
|
||||
if (checked) {
|
||||
AudioManager.playbackRate = value;
|
||||
}
|
||||
playbackRateMenu.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Controls.MenuSeparator {
|
||||
padding: Kirigami.Units.smallSpacing
|
||||
}
|
||||
|
||||
Kirigami.Action {
|
||||
text: i18nc("@action:button", "Customize")
|
||||
icon.name: "settings-configure"
|
||||
onTriggered: {
|
||||
const dialog = customizeDialog.createObject(parent);
|
||||
dialog.open();
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: playbackRateModel
|
||||
|
||||
function resetModel() {
|
||||
playbackRateModel.clear();
|
||||
for (var rate in SettingsManager.playbackRates) {
|
||||
playbackRateModel.append({"value": (SettingsManager.playbackRates[rate] / 100.0).toFixed(2),
|
||||
"name": (SettingsManager.playbackRates[rate] / 100.0).toFixed(2) + "x"});
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
resetModel();
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: customizeDialog
|
||||
PlaybackRateCustomizerDialog {
|
||||
onAccepted: {
|
||||
var newRates = getRateList();
|
||||
SettingsManager.playbackRates = newRates;
|
||||
SettingsManager.save();
|
||||
playbackRateModel.resetModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -459,10 +459,6 @@ Kirigami.ApplicationWindow {
|
|||
}
|
||||
}
|
||||
|
||||
PlaybackRateDialog {
|
||||
id: playbackRateDialog
|
||||
}
|
||||
|
||||
SleepTimerDialog {
|
||||
id: sleepTimerDialog
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
<file alias="UpdateNotification.qml">qml/UpdateNotification.qml</file>
|
||||
<file alias="HeaderBar.qml">qml/Desktop/HeaderBar.qml</file>
|
||||
<file alias="DesktopPlayerControls.qml">qml/Desktop/DesktopPlayerControls.qml</file>
|
||||
<file alias="PlaybackRateDialog.qml">qml/PlaybackRateDialog.qml</file>
|
||||
<file alias="PlaybackRateMenu.qml">qml/PlaybackRateMenu.qml</file>
|
||||
<file alias="PlaybackRateCustomizerDialog.qml">qml/PlaybackRateCustomizerDialog.qml</file>
|
||||
<file alias="ErrorNotification.qml">qml/ErrorNotification.qml</file>
|
||||
<file alias="ConnectionCheckAction.qml">qml/ConnectionCheckAction.qml</file>
|
||||
<file alias="ChapterListDelegate.qml">qml/ChapterListDelegate.qml</file>
|
||||
|
|
|
@ -95,6 +95,12 @@
|
|||
<default></default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Playback Settings">
|
||||
<entry name="playbackRates" type="IntList">
|
||||
<label>List of user-defined playback rates</label>
|
||||
<default>50,75,100,125,150,175,200,225,250</default>
|
||||
</entry>
|
||||
</group>
|
||||
<group name="Network">
|
||||
<entry name="allowMeteredFeedUpdates" type="Bool">
|
||||
<label>Allow podcast updates on metered connections</label>
|
||||
|
|
Loading…
Reference in New Issue