Files
Panama/config/dot/quickshell/modules/settings/KeycapChord.qml
T

110 lines
3.5 KiB
QML

// A key chord, drawn as keys.
//
// KeycapChord { chord: "Super + Shift + Q" }
//
// The chord arrives as the display string Keybinds already produces and is
// split on "+" alone, so nothing here has to know what a keysym is. Modifiers
// are tinted and spelled in title case, which is what makes a wall of chords
// scannable: the eye finds the modifier pattern before it reads the key.
//
// Presentation only. The prettified names are never handed back -- a rebind is
// keyed by the Lua chord the service holds, and this must not become a second,
// lossy spelling of a binding.
import QtQuick
import qs.config
Row {
id: root
property string chord: ""
property int capHeight: 24
readonly property var keys: String(root.chord)
.split("+")
.map(part => part.trim())
.filter(part => part !== "")
// Case-insensitive: Keybinds renders "Super", an override is stored as
// "SUPER", and both have to tint.
readonly property var modifierNames: ({
"super": "Super",
"meta": "Super",
"win": "Super",
"shift": "Shift",
"ctrl": "Ctrl",
"control": "Ctrl",
"alt": "Alt"
})
function isModifier(key: string): bool {
return root.modifierNames[String(key).toLowerCase()] !== undefined;
}
function pretty(key: string): string {
return root.modifierNames[String(key).toLowerCase()] ?? key;
}
spacing: 4
Repeater {
model: root.keys
Row {
id: segment
required property var modelData
required property int index
readonly property bool modifier: root.isModifier(String(segment.modelData))
spacing: 4
Text {
anchors.verticalCenter: parent.verticalCenter
visible: segment.index > 0
text: "+"
color: Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
Rectangle {
anchors.verticalCenter: parent.verticalCenter
width: Math.max(26, cap.implicitWidth + 14)
height: root.capHeight
radius: 6
color: Theme.alpha(Theme.fg, 0.09)
border.width: 1
border.color: Theme.alpha(Theme.fg, 0.16)
// A keycap reads as a key because it has a lip. Rectangle
// borders are uniform, so the thicker bottom edge is its own
// sliver rather than a border width.
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: 1
height: 1
color: Theme.alpha(Theme.fg, 0.16)
}
Text {
id: cap
anchors.centerIn: parent
text: root.pretty(String(segment.modelData))
color: segment.modifier ? Theme.accent : Theme.fg
font.family: Theme.fontMono
// Digits in a chord ("Super + 1") sit in a column of other
// chords; tabular figures keep that column from wobbling.
font.features: Theme.tabularFigures
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
}
}
}
}
}