mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
207 lines
7.0 KiB
QML
207 lines
7.0 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import qs.Common
|
|
import qs.Widgets
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property bool recording: false
|
|
property string capturedToken: ""
|
|
|
|
signal captured(string xkbToken)
|
|
|
|
implicitWidth: 320
|
|
implicitHeight: captureRow.implicitHeight
|
|
|
|
function startRecording() {
|
|
root.recording = true
|
|
captureField.forceActiveFocus()
|
|
root.capturedToken = ""
|
|
}
|
|
|
|
function stopRecording(cancel) {
|
|
root.recording = false
|
|
}
|
|
|
|
function modsFromEvent(mods) {
|
|
const result = []
|
|
if (mods & Qt.ControlModifier) result.push("Ctrl")
|
|
if (mods & Qt.ShiftModifier) result.push("Shift")
|
|
if (mods & Qt.AltModifier) result.push("Alt")
|
|
if (mods & Qt.MetaModifier) result.push("Mod")
|
|
return result
|
|
}
|
|
|
|
function xkbKeyFromQtKey(qk) {
|
|
if (qk >= Qt.Key_A && qk <= Qt.Key_Z) {
|
|
return String.fromCharCode(qk)
|
|
}
|
|
if (qk >= Qt.Key_0 && qk <= Qt.Key_9) {
|
|
return String.fromCharCode(qk)
|
|
}
|
|
|
|
const map = {
|
|
[Qt.Key_Left]: "Left",
|
|
[Qt.Key_Right]: "Right",
|
|
[Qt.Key_Up]: "Up",
|
|
[Qt.Key_Down]: "Down",
|
|
[Qt.Key_Comma]: "Comma",
|
|
[Qt.Key_Period]: "Period",
|
|
[Qt.Key_Slash]: "Slash",
|
|
[Qt.Key_Semicolon]: "Semicolon",
|
|
[Qt.Key_Apostrophe]: "Apostrophe",
|
|
[Qt.Key_BracketLeft]: "BracketLeft",
|
|
[Qt.Key_BracketRight]: "BracketRight",
|
|
[Qt.Key_Backslash]: "Backslash",
|
|
[Qt.Key_Minus]: "Minus",
|
|
[Qt.Key_Equal]: "Equal",
|
|
[Qt.Key_QuoteLeft]: "grave",
|
|
[Qt.Key_Space]: "space",
|
|
[Qt.Key_Print]: "Print",
|
|
[Qt.Key_Return]: "Return",
|
|
[Qt.Key_Enter]: "Return",
|
|
[Qt.Key_Tab]: "Tab",
|
|
[Qt.Key_Backspace]: "BackSpace",
|
|
[Qt.Key_Delete]: "Delete",
|
|
[Qt.Key_Insert]: "Insert",
|
|
[Qt.Key_Home]: "Home",
|
|
[Qt.Key_End]: "End",
|
|
[Qt.Key_PageUp]: "Page_Up",
|
|
[Qt.Key_PageDown]: "Page_Down"
|
|
}
|
|
|
|
if (qk >= Qt.Key_F1 && qk <= Qt.Key_F35) {
|
|
return "F" + (qk - Qt.Key_F1 + 1)
|
|
}
|
|
|
|
return map[qk] || ""
|
|
}
|
|
|
|
function formatToken(mods, key) {
|
|
return (mods.length ? mods.join("+") + "+" : "") + key
|
|
}
|
|
|
|
Row {
|
|
id: captureRow
|
|
width: parent.width
|
|
spacing: Theme.spacingM
|
|
|
|
FocusScope {
|
|
id: captureField
|
|
width: parent.width - recordButton.width - Theme.spacingM
|
|
height: 48
|
|
focus: root.recording
|
|
|
|
Rectangle {
|
|
id: captureBackground
|
|
anchors.fill: parent
|
|
radius: Theme.cornerRadius
|
|
color: root.recording ? Theme.primaryContainer : Theme.surfaceVariant
|
|
border.color: root.recording ? Theme.primary : Theme.primarySelected
|
|
border.width: root.recording ? 2 : 1
|
|
|
|
StyledText {
|
|
anchors.fill: parent
|
|
anchors.leftMargin: Theme.spacingM
|
|
anchors.rightMargin: Theme.spacingM
|
|
text: root.capturedToken || (root.recording ? "Press keys / click / scroll... (Esc cancels)" : "Click Record to capture")
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
color: root.capturedToken ? Theme.surfaceText : Theme.surfaceVariantText
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
Behavior on color {
|
|
ColorAnimation {
|
|
duration: Theme.shortDuration
|
|
easing.type: Theme.standardEasing
|
|
}
|
|
}
|
|
|
|
Behavior on border.color {
|
|
ColorAnimation {
|
|
duration: Theme.shortDuration
|
|
easing.type: Theme.standardEasing
|
|
}
|
|
}
|
|
}
|
|
|
|
Keys.onPressed: (event) => {
|
|
if (!root.recording) return
|
|
|
|
if (event.key === Qt.Key_Escape) {
|
|
root.stopRecording(true)
|
|
event.accepted = true
|
|
return
|
|
}
|
|
|
|
const onlyModifier = [Qt.Key_Control, Qt.Key_Shift, Qt.Key_Alt, Qt.Key_Meta].includes(event.key)
|
|
if (onlyModifier) {
|
|
event.accepted = true
|
|
return
|
|
}
|
|
|
|
const mods = root.modsFromEvent(event.modifiers)
|
|
const key = root.xkbKeyFromQtKey(event.key)
|
|
if (key) {
|
|
const token = root.formatToken(mods, key)
|
|
root.capturedToken = token
|
|
root.captured(token)
|
|
root.stopRecording(false)
|
|
event.accepted = true
|
|
}
|
|
}
|
|
|
|
TapHandler {
|
|
acceptedButtons: Qt.AllButtons
|
|
enabled: root.recording
|
|
onTapped: (eventPoint, button) => {
|
|
const mods = root.modsFromEvent(eventPoint.modifiers)
|
|
let key = ""
|
|
if (button === Qt.LeftButton) key = "MouseLeft"
|
|
else if (button === Qt.RightButton) key = "MouseRight"
|
|
else if (button === Qt.MiddleButton) key = "MouseMiddle"
|
|
else if (button === Qt.BackButton) key = "MouseBack"
|
|
else if (button === Qt.ForwardButton) key = "MouseForward"
|
|
|
|
if (key) {
|
|
const token = root.formatToken(mods, key)
|
|
root.capturedToken = token
|
|
root.captured(token)
|
|
root.stopRecording(false)
|
|
}
|
|
}
|
|
}
|
|
|
|
WheelHandler {
|
|
enabled: root.recording
|
|
onWheel: (event) => {
|
|
const mods = root.modsFromEvent(event.modifiers)
|
|
let key = ""
|
|
if (Math.abs(event.angleDelta.y) >= Math.abs(event.angleDelta.x)) {
|
|
key = event.angleDelta.y < 0 ? "WheelScrollDown" : "WheelScrollUp"
|
|
} else {
|
|
key = event.angleDelta.x < 0 ? "WheelScrollRight" : "WheelScrollLeft"
|
|
}
|
|
const token = root.formatToken(mods, key)
|
|
root.capturedToken = token
|
|
root.captured(token)
|
|
root.stopRecording(false)
|
|
event.accepted = true
|
|
}
|
|
}
|
|
}
|
|
|
|
DankActionButton {
|
|
id: recordButton
|
|
width: 48
|
|
height: 48
|
|
circular: false
|
|
iconName: recording ? "close" : "radio_button_checked"
|
|
iconSize: Theme.iconSize
|
|
iconColor: recording ? Theme.error : Theme.primary
|
|
onClicked: recording ? root.stopRecording(true) : root.startRecording()
|
|
}
|
|
}
|
|
} |