shift-shell/components/mobileshell/qml/popups/volumeosd/VolumeSlider.qml
Marco Allegretti 7f9087f342 Move shell popups to shared motion
Apply Motion tokens to notification drag and stack transitions, volume OSD feedback, KRunner field state, media controls height changes, and action-button popup affordances. Leave timeout and marquee animations as timing behavior.
2026-05-21 11:13:06 +02:00

131 lines
5.3 KiB
QML

/*
SPDX-FileCopyrightText: 2014-2015 Harald Sitter <sitter@kde.org>
SPDX-FileCopyrightText: 2019 Sefa Eyeoglu <contact@scrumplex.net>
SPDX-FileCopyrightText: 2022 ivan (@ratijas) tkachenko <me@ratijas.tk>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
import QtQuick
import QtQuick.Layouts
import org.kde.kquickcontrolsaddons
import org.kde.plasma.components as PC3
import org.kde.ksvg as KSvg
import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.volume
// Audio volume slider. Value represents desired volume level in
// device-specific units, while volume property reports current volume level
// normalized to 0..1 range.
PC3.Slider {
id: control
property VolumeObject volumeObject
readonly property real mutedOpacity: 0.55
// When muted, the whole slider will appear slightly faded, but remain
// functional and interactive.
property bool muted: false
// Current (monitored) volume. To be animated. Do not update too fast
// (i.e. faster or close to screen refresh rate), otherwise it won't
// animate smoothly.
property real volume: meter.volume
VolumeMonitor {
id: meter
target: control.visible ? control.volumeObject : null
}
Behavior on volume {
MobileShell.MotionNumberAnimation {
id: animate
type: MobileShell.Motion.EffectsFast
}
}
// When a maximum volume limit is raised/lower, animate the change.
Behavior on to {
MobileShell.MotionNumberAnimation {
type: MobileShell.Motion.EffectsFast
}
}
opacity: muted ? mutedOpacity : 1
// Prevents the groove from showing through the handle
layer.enabled: opacity < 1
wheelEnabled: false
// `wheelEnabled: true` doesn't work we can't both respect stepsize
// on scroll and allow fine-tuning on drag.
// So we have to implement the scroll handling ourselves. See
// https://bugreports.qt.io/browse/QTBUG-93081
WheelHandler {
orientation: Qt.Vertical | Qt.Horizontal
property int wheelDelta: 0
acceptedButtons: Qt.NoButton
acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
onWheel: wheel => {
const lastValue = control.value
// We want a positive delta to increase the slider for up/right scrolling,
// independently of the scrolling inversion setting
// The x-axis is also inverted (scrolling right produce negative values)
const delta = (wheel.angleDelta.y || -wheel.angleDelta.x) * (wheel.inverted ? -1 : 1)
wheelDelta += delta;
// magic number 120 for common "one click"
// See: https://doc.qt.io/qt-6/qml-qtquick-wheelevent.html#angleDelta-prop
while (wheelDelta >= 120) {
wheelDelta -= 120;
control.increase();
}
while (wheelDelta <= -120) {
wheelDelta += 120;
control.decrease();
}
if (lastValue !== control.value) {
control.moved();
}
}
}
background: KSvg.FrameSvgItem {
imagePath: "widgets/slider"
prefix: "groove"
implicitWidth: control.horizontal ? Kirigami.Units.gridUnit * 12 : fixedMargins.left + fixedMargins.right
implicitHeight: control.vertical ? Kirigami.Units.gridUnit * 12 : fixedMargins.top + fixedMargins.bottom
width: control.horizontal ? Math.max(fixedMargins.left + fixedMargins.right, control.availableWidth) : implicitWidth
height: control.vertical ? Math.max(fixedMargins.top + fixedMargins.bottom, control.availableHeight) : implicitHeight
x: control.leftPadding + (control.horizontal ? 0 : Math.round((control.availableWidth - width) / 2))
y: control.topPadding + (control.vertical ? 0 : Math.round((control.availableHeight - height) / 2))
KSvg.FrameSvgItem {
imagePath: "widgets/slider"
prefix: "groove-highlight"
anchors.left: parent.left
anchors.bottom: parent.bottom
LayoutMirroring.enabled: control.mirrored
width: control.horizontal ? Math.max(fixedMargins.left + fixedMargins.right, Math.round(control.position * (control.availableWidth - control.handle.width / 2) + (control.handle.width / 2))) : parent.width
height: control.vertical ? Math.max(fixedMargins.top + fixedMargins.bottom, Math.round(control.position * (control.availableHeight - control.handle.height / 2) + (control.handle.height / 2))) : parent.height
}
KSvg.FrameSvgItem {
imagePath: "widgets/slider"
prefix: "groove-highlight"
status: KSvg.FrameSvgItem.Selected
visible: meter.available && control.volume > 0
anchors.left: parent.left
anchors.bottom: parent.bottom
LayoutMirroring.enabled: control.mirrored
width: control.horizontal ? Math.max(fixedMargins.left + fixedMargins.right, Math.round(control.volume * control.position * control.availableWidth)) : parent.width
height: control.vertical ? Math.max(fixedMargins.top + fixedMargins.bottom, Math.round(control.volume * control.position * control.availableHeight)) : parent.height
}
}
}