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:
parent
3749d1e135
commit
8de26c11a1
|
@ -115,7 +115,7 @@ class UISettings(JSONConfigFile):
|
|||
"theme": "Default.qpl",
|
||||
"writeAliases": {},
|
||||
"keys": {
|
||||
"reloadConfig": ["Alt+Shift+R"],
|
||||
"reloadConfig": "Alt+Shift+R",
|
||||
"scrollUp": ["Alt+Up", "Alt+K"],
|
||||
"scrollDown": ["Alt+Down", "Alt+J"],
|
||||
"focusSidePane": ["Alt+S", "Ctrl+S"],
|
||||
|
|
|
@ -26,5 +26,7 @@ ScrollView {
|
|||
id: textAreaBackground
|
||||
color: theme.controls.textArea.background
|
||||
}
|
||||
|
||||
Keys.forwardTo: mainUI.shortcuts
|
||||
}
|
||||
}
|
||||
|
|
10
src/qml/Base/HShortcut.qml
Normal file
10
src/qml/Base/HShortcut.qml
Normal 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
|
||||
}
|
56
src/qml/Base/HShortcutHandler.qml
Normal file
56
src/qml/Base/HShortcutHandler.qml
Normal 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
|
||||
}
|
||||
}
|
|
@ -28,4 +28,5 @@ TextField {
|
|||
}
|
||||
|
||||
selectByMouse: true
|
||||
Keys.forwardTo: mainUI.shortcuts
|
||||
}
|
||||
|
|
|
@ -1,80 +1,54 @@
|
|||
import QtQuick 2.12
|
||||
import "Base"
|
||||
import "utils.js" as Utils
|
||||
|
||||
Item {
|
||||
HShortcutHandler {
|
||||
property Item flickTarget: Item {}
|
||||
|
||||
|
||||
function smartVerticalFlick(baseVelocity, fastMultiply=3) {
|
||||
if (! flickTarget.interactive) { return }
|
||||
|
||||
baseVelocity = -baseVelocity
|
||||
let vel = -flickTarget.verticalVelocity
|
||||
let fast = (baseVelocity < 0 && vel < baseVelocity / 2) ||
|
||||
(baseVelocity > 0 && vel > baseVelocity / 2)
|
||||
|
||||
flickTarget.flick(0, baseVelocity * (fast ? fastMultiply : 1))
|
||||
HShortcut {
|
||||
enabled: debugMode
|
||||
sequences: settings.keys.startDebugger
|
||||
onPressed: py.call("APP.pdb")
|
||||
}
|
||||
|
||||
|
||||
Shortcut {
|
||||
sequences: settings.keys ? settings.keys.startDebugger : []
|
||||
onActivated: if (debugMode) { py.call("APP.pdb") }
|
||||
HShortcut {
|
||||
sequences: settings.keys.reloadConfig
|
||||
onPressed: py.loadSettings(() => { mainUI.pressAnimation.start() })
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: settings.keys ? settings.keys.reloadConfig : []
|
||||
onActivated: py.loadSettings(() => { mainUI.pressAnimation.start() })
|
||||
HShortcut {
|
||||
sequences: settings.keys.scrollUp
|
||||
onPressed: Utils.smartVerticalFlick(flickTarget, -335)
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: settings.keys ? settings.keys.scrollUp : []
|
||||
onActivated: smartVerticalFlick(-335)
|
||||
HShortcut {
|
||||
sequences: settings.keys.scrollDown
|
||||
onPressed: Utils.smartVerticalFlick(flickTarget, 335)
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: settings.keys ? settings.keys.scrollDown : []
|
||||
onActivated: smartVerticalFlick(335)
|
||||
HShortcut {
|
||||
sequences: settings.keys.focusSidePane
|
||||
onPressed: mainUI.sidePane.setFocus()
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: settings.keys ? settings.keys.focusSidePane : []
|
||||
onActivated: mainUI.sidePane.setFocus()
|
||||
HShortcut {
|
||||
sequences: settings.keys.clearRoomFilter
|
||||
onPressed: mainUI.sidePane.paneToolBar.roomFilter = ""
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: settings.keys ? settings.keys.clearRoomFilter : []
|
||||
onActivated: mainUI.sidePane.paneToolBar.roomFilter = ""
|
||||
HShortcut {
|
||||
sequences: settings.keys.goToPreviousRoom
|
||||
onPressed: mainUI.sidePane.accountRoomList.previous()
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: settings.keys ? settings.keys.goToPreviousRoom : []
|
||||
onActivated: mainUI.sidePane.accountRoomList.previous()
|
||||
HShortcut {
|
||||
sequences: settings.keys.goToNextRoom
|
||||
onPressed: mainUI.sidePane.accountRoomList.next()
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: settings.keys ? settings.keys.goToNextRoom : []
|
||||
onActivated: mainUI.sidePane.accountRoomList.next()
|
||||
HShortcut {
|
||||
sequences: settings.keys.toggleCollapseAccount
|
||||
onPressed: mainUI.sidePane.accountRoomList.toggleCollapseAccount()
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequences: settings.keys ? settings.keys.toggleCollapseAccount : []
|
||||
onActivated: mainUI.sidePane.accountRoomList.toggleCollapseAccount()
|
||||
}
|
||||
|
||||
/*
|
||||
Shortcut {
|
||||
sequence: "Ctrl+-"
|
||||
onActivated: theme.fontScale = Math.max(0.1, theme.fontScale - 0.1)
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: "Ctrl++"
|
||||
onActivated: theme.fontScale = Math.min(10, theme.fontScale + 0.1)
|
||||
}
|
||||
|
||||
Shortcut {
|
||||
sequence: "Ctrl+="
|
||||
onActivated: theme.fontScale = 1.0
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ HRectangle {
|
|||
color: theme.ui.background
|
||||
Component.onCompleted: window.mainUI = mainUI
|
||||
|
||||
property alias shortcuts: shortcuts
|
||||
property alias sidePane: sidePane
|
||||
property alias pageLoader: pageLoader
|
||||
property alias pressAnimation: _pressAnimation
|
||||
|
@ -28,6 +29,9 @@ HRectangle {
|
|||
(modelSources["Account"] || []).length > 0 ||
|
||||
py.startupAnyAccountsSaved
|
||||
|
||||
|
||||
Shortcuts { id: shortcuts }
|
||||
|
||||
HImage {
|
||||
id: mainUIBackground
|
||||
visible: Boolean(Qt.resolvedUrl(source))
|
||||
|
|
|
@ -27,7 +27,6 @@ ApplicationWindow {
|
|||
|
||||
property var theme: null
|
||||
|
||||
Shortcuts { id: shortcuts}
|
||||
Python { id: py }
|
||||
|
||||
HLoader {
|
||||
|
|
|
@ -162,3 +162,15 @@ function getItem(array, mainKey, value) {
|
|||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
||||
function smartVerticalFlick(flickTarget, baseVelocity, fastMultiply=3) {
|
||||
if (! flickTarget.interactive) { return }
|
||||
|
||||
baseVelocity = -baseVelocity
|
||||
let vel = -flickTarget.verticalVelocity
|
||||
let fast = (baseVelocity < 0 && vel < baseVelocity / 2) ||
|
||||
(baseVelocity > 0 && vel > baseVelocity / 2)
|
||||
|
||||
flickTarget.flick(0, baseVelocity * (fast ? fastMultiply : 1))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user