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

150 lines
4.6 KiB
QML

// One shortcut in the shortcuts browser.
//
// There are around a hundred and thirty of these on the page at once, so the
// row is deliberately plain: no Loader for the row itself, no animations, and
// the Change/Reset buttons are ordinary children that hide when the pointer is
// elsewhere. Only the capture field is loaded on demand -- it is a FocusScope
// nobody needs until they ask to rebind, and instantiating one per row is a
// hundred and thirty focus scopes for a single edit.
//
// The row reports what was pressed and never decides anything: conflicts,
// refusals and the write itself belong to the page, which is where the one
// capture at a time is tracked.
import QtQuick
import qs.config
import qs.services
Item {
id: root
required property var bind
property bool capturing: false
property bool divider: true
// Shown inside the capture field -- the page puts a refused chord here.
property string message: ""
signal changeRequested
signal resetRequested
signal captured(string chord)
signal canceled
readonly property bool overridden: Keybinds.isOverridden(root.bind.luaChord)
width: parent ? parent.width : 620
implicitHeight: 42
Rectangle {
anchors.fill: parent
anchors.bottomMargin: 2
radius: 9
visible: hover.containsMouse || root.capturing
color: root.capturing
? Theme.alpha(Theme.accent, 0.10)
: Theme.alpha(Theme.fg, 0.05)
}
MouseArea {
id: hover
anchors.fill: parent
hoverEnabled: true
// Hover only. Accepting buttons here would put a click target over the
// whole row and swallow presses meant for Change and Reset.
acceptedButtons: Qt.NoButton
}
Text {
anchors.left: parent.left
anchors.leftMargin: 6
anchors.right: trailing.left
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: String(root.bind.description ?? "")
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
elide: Text.ElideRight
}
Row {
id: trailing
anchors.right: parent.right
anchors.rightMargin: 6
anchors.verticalCenter: parent.verticalCenter
visible: !root.capturing
spacing: 8
// Where it used to be. Only while the row is under the pointer: at rest
// the badge says a shortcut moved, and this says where from, which is
// the question the badge raises and nothing else answers.
Text {
anchors.verticalCenter: parent.verticalCenter
visible: root.overridden && hover.containsMouse
text: "was " + Keybinds.shippedChordFor(root.bind.luaChord)
color: Theme.fgMuted
font.family: Theme.fontMono
font.pixelSize: Theme.fontSizeSmall
}
StatusBadge {
anchors.verticalCenter: parent.verticalCenter
visible: root.overridden
text: "Changed"
tone: Theme.warn
}
SettingsButton {
anchors.verticalCenter: parent.verticalCenter
visible: hover.containsMouse
text: "Change"
// A scroll or click bind has no key to capture.
enabled: !Keybinds.reloading && !root.bind.mouse
onClicked: root.changeRequested()
}
SettingsButton {
anchors.verticalCenter: parent.verticalCenter
visible: hover.containsMouse && root.overridden
text: "Reset"
enabled: !Keybinds.reloading
onClicked: root.resetRequested()
}
KeycapChord {
anchors.verticalCenter: parent.verticalCenter
chord: String(root.bind.chord ?? "")
}
}
Loader {
anchors.right: parent.right
anchors.rightMargin: 6
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()
}
}
Rectangle {
anchors.left: parent.left
anchors.leftMargin: 6
anchors.right: parent.right
anchors.rightMargin: 6
anchors.bottom: parent.bottom
height: 1
visible: root.divider
color: Theme.alpha(Theme.fg, 0.05)
}
}