HShortcutHandler & HShortcut components

Provide more powerful shortcuts handling than what's available with
QML's Shortcut component, notably being able to react differently to key
presses, releases and auto-repeats.
This commit is contained in:
miruka
2019-08-22 13:03:26 -04:00
parent 3749d1e135
commit 8de26c11a1
9 changed files with 118 additions and 60 deletions

View File

@@ -26,5 +26,7 @@ ScrollView {
id: textAreaBackground
color: theme.controls.textArea.background
}
Keys.forwardTo: mainUI.shortcuts
}
}

View File

@@ -0,0 +1,10 @@
import QtQuick 2.12
QtObject {
signal pressed(var event)
signal held(var event)
signal released(var event)
property bool enabled: true
property var sequences: "" // string or array of strings
}

View File

@@ -0,0 +1,56 @@
import QtQuick 2.12
Item {
id: shortcutHandler
Keys.onPressed: {
let shortcut = match(event)
if (! shortcut) return
event.isAutoRepeat ? shortcut.held(event) : shortcut.pressed(event)
}
Keys.onReleased: {
let shortcut = match(event)
if (shortcut && ! event.isAutoRepeat) shortcut.released(event)
}
readonly property var modifierDict: ({
Ctrl: Qt.ControlModifier,
Shift: Qt.ShiftModifier,
Alt: Qt.AltModifier,
Meta: Qt.MetaModifier,
})
function sequenceMatches(event, sequence) {
let [key, ...mods] = sequence.split("+").reverse()
key = key.charAt(0).toUpperCase() + key.slice(1)
if (event.key !== Qt["Key_" + key]) return false
for (let [name, code] of Object.entries(modifierDict)) {
if (mods.includes(name) && ! (event.modifiers & code)) return false
if (! mods.includes(name) && event.modifiers & code) return false
}
return true
}
function match(event) {
for (let i = 0; i < shortcutHandler.resources.length; i++) {
let shortcut = shortcutHandler.resources[i]
if (! shortcut.enabled) continue
if (typeof(shortcut.sequences) == "string" &&
sequenceMatches(event, shortcut.sequences)) return shortcut
for (let i = 0; i < shortcut.sequences.length; i++) {
if (sequenceMatches(event, shortcut.sequences[i]))
return shortcut
}
}
return null
}
}

View File

@@ -28,4 +28,5 @@ TextField {
}
selectByMouse: true
Keys.forwardTo: mainUI.shortcuts
}