95 lines
3.3 KiB
QML
95 lines
3.3 KiB
QML
// One shortcut the user invented, in the pinned Custom group.
|
|
//
|
|
// ShortcutRow renders a bind the compositor reported; this renders a stored
|
|
// `customBinds` entry, which is a different thing and deliberately not the same
|
|
// component. A custom bind has an action to describe (the compositor reports
|
|
// every Lua bind as "__lua" plus a bytecode offset, so the description has to
|
|
// come from the entry), it is removable, and it is never "overridden" -- a
|
|
// rebind rewrites the entry in place rather than adding to the override map.
|
|
//
|
|
// The row reports and never decides: conflicts, the write and the reload all
|
|
// belong to Keybinds, and the page owns the one capture at a time.
|
|
|
|
import QtQuick
|
|
import qs.config
|
|
import qs.services
|
|
|
|
SettingRow {
|
|
id: root
|
|
|
|
required property var entry
|
|
property bool capturing: false
|
|
// Shown inside the capture field -- the page puts a refused chord here.
|
|
property string message: ""
|
|
|
|
signal rebindRequested
|
|
signal removeRequested
|
|
signal captured(string chord)
|
|
signal canceled
|
|
|
|
readonly property string chord: String(root.entry?.chord ?? "")
|
|
readonly property string action: Keybinds.describeAction(root.entry)
|
|
|
|
// A stored entry is an intention; the keymap is the fact. hypr/keybinds.lua
|
|
// skips an entry whose action does not resolve or whose chord a shipped
|
|
// bind already holds, and a shortcut that quietly does nothing is exactly
|
|
// what a settings page must not draw as working.
|
|
readonly property bool live: root.action !== "" && Keybinds.customBindApplied(root.entry)
|
|
|
|
label: String(root.entry?.label ?? "")
|
|
detail: root.action === ""
|
|
? "This shortcut names an action Panama no longer has — remove it"
|
|
: (root.live
|
|
? root.action
|
|
: root.action + " · not answering yet — the compositor reloads on save")
|
|
labelColor: root.action === "" ? Theme.danger : Theme.fg
|
|
controlWidth: root.capturing ? 250 : (removeConfirm.armed ? 330 : 250)
|
|
|
|
Row {
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
visible: !root.capturing
|
|
spacing: 8
|
|
|
|
SettingsButton {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: "Rebind"
|
|
enabled: !Keybinds.reloading
|
|
onClicked: root.rebindRequested()
|
|
}
|
|
|
|
ConfirmAction {
|
|
id: removeConfirm
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
actionId: "custom-bind-remove:" + root.chord
|
|
armText: "Remove…"
|
|
confirmText: "Remove it"
|
|
enabled: !Keybinds.reloading
|
|
onConfirmed: root.removeRequested()
|
|
}
|
|
|
|
KeycapChord {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
chord: root.chord
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: 240
|
|
height: 30
|
|
active: root.capturing
|
|
// Focus has to travel through the Loader for the capture inside it to
|
|
// ever see a key press.
|
|
focus: root.capturing
|
|
sourceComponent: ShortcutCapture {
|
|
focus: true
|
|
message: root.message
|
|
onCaptured: chord => root.captured(chord)
|
|
onCanceled: root.canceled()
|
|
}
|
|
}
|
|
}
|