colour -> color, behaviour -> behavior, centre -> center, favourite -> favorite, and about twenty other pairs, applied consistently across comments, docs, error/UI copy, and a handful of QML identifiers that used the British spelling as their actual name: SystemSettings' serialiseValue/serialiseTable/normaliseGradient, Displays' normaliseModes, Wallpaper's normalisePolicy, SettingsBackup's serialiseHomeState, DateTime's ntpSynchronised property, Clipboard's _normalise helper, and ShortcutCapture's cancelled signal (with its onCancelled handler in ShortcutsPage.qml). Every call site and the two tests that assert on the literal source text (settings-ownership and settings-backup-live contracts) were updated in lockstep. Left untouched: config/dot/espanso/match/packages/misspell-en/ is a vendored third-party autocorrect dictionary -- its entries are typo corrections, not our prose, and rewriting them would fight the package's own purpose (and any future re-sync from upstream). The already-American `favorites` property (Home page pinned accessories) was never actually misspelled -- only nearby comments and error strings said "favourites" -- so no data migration was needed there. Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
127 lines
4.2 KiB
QML
127 lines
4.2 KiB
QML
// A GNOME-style slider: a thick rounded track with an inline leading icon,
|
|
// used for volume and brightness in the quick settings panel.
|
|
//
|
|
// Deliberately not QtQuick.Controls.Slider — that pulls in a style plugin and
|
|
// fights the theme. This is ~50 lines and does exactly what's needed.
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Widgets
|
|
import qs.config
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property real value: 0 // 0.0 .. 1.0
|
|
property string icon: ""
|
|
property bool enabled: true
|
|
|
|
// Emitted continuously while dragging.
|
|
signal moved(real value)
|
|
|
|
implicitWidth: 240
|
|
implicitHeight: 32
|
|
|
|
opacity: enabled ? 1.0 : 0.45
|
|
|
|
// ThemedIcon, not a bare IconImage — see the note in Toggle.qml: Adwaita
|
|
// symbolic icons have a hardcoded near-black fill that Qt will not recolor.
|
|
ThemedIcon {
|
|
id: leadingIcon
|
|
anchors.left: parent.left
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
size: 18
|
|
icon: root.icon
|
|
tint: Theme.fg
|
|
visible: root.icon !== ""
|
|
}
|
|
|
|
Rectangle {
|
|
id: track
|
|
anchors.left: leadingIcon.visible ? leadingIcon.right : parent.left
|
|
anchors.leftMargin: leadingIcon.visible ? 10 : 0
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
height: 10
|
|
radius: height / 2
|
|
color: Theme.alpha(Theme.fg, 0.12)
|
|
border.width: 0
|
|
|
|
Rectangle {
|
|
id: fill
|
|
anchors.left: parent.left
|
|
anchors.top: parent.top
|
|
anchors.bottom: parent.bottom
|
|
width: parent.width * Math.max(0, Math.min(1, root.value))
|
|
radius: parent.radius
|
|
border.width: 0
|
|
|
|
// The gradient is anchored to the full track, not to the fill, so
|
|
// the color at a given position never moves as the value changes —
|
|
// dragging reveals the prism rather than squashing it.
|
|
gradient: Gradient {
|
|
orientation: Gradient.Horizontal
|
|
GradientStop {
|
|
position: 0.0
|
|
color: Theme.accent
|
|
}
|
|
GradientStop {
|
|
position: 1.0
|
|
color: Theme.mix(Theme.accent, Theme.accentSecondary, Math.max(0.001, Math.min(1, root.value)))
|
|
}
|
|
}
|
|
|
|
// Only animates when the value changes from outside (e.g. a media
|
|
// key); dragging sets it directly and reads as instant.
|
|
Behavior on width {
|
|
enabled: !drag.pressed
|
|
NumberAnimation {
|
|
duration: Theme.durFast
|
|
easing.type: Easing.OutQuad
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: knob
|
|
width: 16
|
|
height: 16
|
|
radius: 8
|
|
border.width: 0
|
|
color: Theme.fg
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
x: Math.max(0, Math.min(parent.width - width, fill.width - width / 2))
|
|
visible: drag.containsMouse || drag.pressed
|
|
}
|
|
|
|
MouseArea {
|
|
id: drag
|
|
anchors.fill: parent
|
|
anchors.margins: -8 // easier to grab than a 10px track
|
|
enabled: root.enabled
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
|
|
function apply(mouseX) {
|
|
// mouseX is local to this MouseArea, whose anchors.margins: -8
|
|
// pushes its own origin 8px before the track's left edge. So
|
|
// MouseArea-local x=8 is track-local x=0 -- subtract the
|
|
// margin to land back in the track's own coordinate space
|
|
// before turning it into a fraction.
|
|
const ratio = Math.max(0, Math.min(1, (mouseX - 8) / track.width));
|
|
root.moved(ratio);
|
|
}
|
|
|
|
onPressed: event => apply(event.x)
|
|
onPositionChanged: event => {
|
|
if (pressed)
|
|
apply(event.x);
|
|
}
|
|
onWheel: event => {
|
|
const step = event.angleDelta.y > 0 ? 0.05 : -0.05;
|
|
root.moved(Math.max(0, Math.min(1, root.value + step)));
|
|
}
|
|
}
|
|
}
|
|
}
|