// Copyright (C) 2026 Danilo M. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. import Quickshell import Quickshell.Widgets import QtQuick import ".." // An icon, a track and a label: drag or click sets, the wheel steps one per // notch. Shared by the headphones and Sonix panels. The width is the user's. Row { id: row property int cp: 0 property string icon: "" property real value: 0 property bool muted: false property string label: "" signal moved(real v) signal stepped(int d) signal iconClicked() spacing: 10 Item { anchors.verticalCenter: parent.verticalCenter width: 20 height: 20 Text { visible: row.icon === "" anchors.centerIn: parent text: String.fromCodePoint(row.cp) font { family: Theme.iconFamily; pixelSize: 20 } color: Theme.subtext } IconImage { visible: row.icon !== "" anchors.centerIn: parent implicitSize: 18 source: row.icon !== "" ? Quickshell.iconPath(row.icon, true) : "" } MouseArea { anchors.fill: parent enabled: row.enabled cursorShape: Qt.PointingHandCursor onClicked: row.iconClicked() } } Rectangle { anchors.verticalCenter: parent.verticalCenter width: row.width - 20 - 44 - row.spacing * 2 height: 8 radius: 4 color: Theme.surface Rectangle { height: parent.height radius: parent.radius width: parent.width * Math.max(0, Math.min(1, row.value)) color: row.muted ? Theme.red : Theme.accent opacity: row.muted ? 0.5 : 1 } // Taller than the track so it is easy to hit. A MouseArea for the // wheel, not a WheelHandler (AGENTS.md); one step per notch (120), // since a touchpad sends many small deltas. MouseArea { anchors { fill: parent; topMargin: -8; bottomMargin: -8 } enabled: row.enabled preventStealing: true cursorShape: Qt.PointingHandCursor property real acc: 0 function at(x) { return Math.max(0, Math.min(1, x / width)); } onPressed: mouse => row.moved(at(mouse.x)) onPositionChanged: mouse => { if (pressed) row.moved(at(mouse.x)); } onWheel: wheel => { acc += wheel.angleDelta.y; while (Math.abs(acc) >= 120) { row.stepped(acc > 0 ? 1 : -1); acc -= acc > 0 ? 120 : -120; } wheel.accepted = true; } } } Text { anchors.verticalCenter: parent.verticalCenter width: 44 horizontalAlignment: Text.AlignRight text: row.label font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } color: row.muted ? Theme.red : Theme.subtext } }