Files
dms-gamebar/components/VolumeRow.qml
T

100 lines
2.8 KiB
QML

import QtQuick
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: row
property var node: null
property int maxPercent: 100
property string activeIcon: "volume_up"
property string mutedIcon: "volume_off"
readonly property var audio: (node && node.audio) ? node.audio : null
readonly property bool muted: audio ? audio.muted : false
readonly property int percent: audio ? Math.round(audio.volume * 100) : 0
readonly property int sliderMaximum: Math.max(100, maxPercent)
// DankSlider assigns its own `value` while dragging, which breaks a declarative
// binding, so the slider is synced imperatively whenever the node volume changes.
function syncSlider() {
slider.value = Math.min(row.sliderMaximum, row.percent);
}
function applyVolume(newValue) {
if (!row.audio)
return;
row.audio.volume = newValue / 100;
if (newValue > 0 && row.audio.muted)
row.audio.muted = false;
}
height: 48
onPercentChanged: row.syncSlider()
onSliderMaximumChanged: row.syncSlider()
onNodeChanged: row.syncSlider()
Rectangle {
id: muteButton
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 40
height: 40
radius: width / 2
color: muteArea.containsMouse ? Theme.primaryHover : "transparent"
DankIcon {
anchors.centerIn: parent
name: (row.muted || row.percent === 0) ? row.mutedIcon : row.activeIcon
size: Theme.iconSize
color: row.muted ? Theme.error : Theme.primary
}
MouseArea {
id: muteArea
anchors.fill: parent
hoverEnabled: true
enabled: row.audio !== null
cursorShape: Qt.PointingHandCursor
onClicked: {
if (row.audio)
row.audio.muted = !row.audio.muted;
}
}
}
StyledText {
id: valueLabel
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
width: 48
horizontalAlignment: Text.AlignRight
text: row.percent + "%"
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: row.muted ? Theme.surfaceVariantText : Theme.surfaceText
}
DankSlider {
id: slider
anchors.left: muteButton.right
anchors.leftMargin: Theme.spacingS
anchors.right: valueLabel.left
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
enabled: row.audio !== null
minimum: 0
maximum: row.sliderMaximum
showValue: false
onSliderValueChanged: newValue => row.applyVolume(newValue)
Component.onCompleted: row.syncSlider()
}
}