165 lines
5.1 KiB
QML
165 lines
5.1 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
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
visible: root.overridden
|
|
width: badge.implicitWidth + 14
|
|
height: 18
|
|
radius: Theme.pillRadius
|
|
color: Theme.alpha(Theme.warn, 0.10)
|
|
border.width: 1
|
|
border.color: Theme.alpha(Theme.warn, 0.32)
|
|
|
|
Text {
|
|
id: badge
|
|
|
|
anchors.centerIn: parent
|
|
text: "CHANGED"
|
|
color: Theme.warn
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Math.max(8, Theme.fontSizeSmall - 2)
|
|
font.weight: Font.DemiBold
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|