Skip to content

Commit

Permalink
Enhancement: Implemented keyboard shortcut persistence, solving issues
Browse files Browse the repository at this point in the history
…#53 and #75. Made next and previous anchor shortcut customization independent from move backwards and move forwards shortcuts, solving issue #65. Re-implemented Prompter's keyboard input management to enable using modifier keys as part of shortcuts, multiplying number of possible input combinations.
  • Loading branch information
Cuperino committed Mar 18, 2022
1 parent bb16784 commit bd8e2a9
Show file tree
Hide file tree
Showing 9 changed files with 267 additions and 238 deletions.
3 changes: 3 additions & 0 deletions .kdev4/QPrompt.kdev4
Expand Up @@ -134,3 +134,6 @@ isExecutable=false

[Project]
VersionControlSupport=kdevgit

[SourceFileTemplates]
LastUsedTemplate=/home/javier/.local/share/kdevfiletemplates/template_descriptions/qobject.desktop
4 changes: 2 additions & 2 deletions CMakeLists.txt
Expand Up @@ -247,7 +247,7 @@ if(UNIX AND NOT ANDROID)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5svg5 (>= 5.15.2), qml-module-qt-labs-platform (>=5.15.2), qml-module-qtqml (>=5.15.2), qml-module-qtqml-models2 (>=5.15.2), qml-module-qtqml-statemachine (>=5.15.2), qml-module-qtquick-controls (>=5.15.2), qml-module-qtquick-controls2 (>=5.15.2), qml-module-qtquick-dialogs (>=5.15.2), qml-module-qtquick-shapes (>=5.15.2), qml-module-org-kde-kirigami2 (>=5.78.0), libkf5i18n5 (>= 5.78.0), libkf5coreaddons5 (>= 5.78.0)")

# CPACK: RPM Specific Settings
set(CPACK_RPM_PACKAGE_LICENSE "GPLv3+")
set(CPACK_RPM_PACKAGE_LICENSE "GPLv3")
set(CPACK_RPM_PACKAGE_GROUP "Multimedia/Video")
set(CPACK_RPM_PACKAGE_URL ${PROJECT_URL})
set(CPACK_RPM_COMPRESSION_TYPE ${COMPRESION_TYPE})
Expand Down Expand Up @@ -292,5 +292,5 @@ include(CPack)

feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) # INCLUDE_QUIET_PACKAGES

file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h)
file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h *.hpp)
kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES})
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Expand Up @@ -31,6 +31,7 @@ set(qprompt_HDRS
prompter/documenthandler.h
prompter/markersmodel.h
#prompter/timer/promptertimer.h
qt/qmlutil.hpp
)

set(qprompt_ASSETS
Expand Down
72 changes: 56 additions & 16 deletions src/kirigami_ui/InputsOverlay.qml
Expand Up @@ -24,6 +24,8 @@ import org.kde.kirigami 2.11 as Kirigami
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

import com.cuperino.qprompt.qmlutil 1.0

Kirigami.OverlaySheet {
id: key_configuration_overlay

Expand Down Expand Up @@ -51,42 +53,78 @@ Kirigami.OverlaySheet {
}

Component.onCompleted: {
keyInputTogglePrompter.setSource("KeyInputButton.qml", { "text": "F9" });
keyInputDecreaseVelocity.setSource("KeyInputButton.qml", { "text": "Up Arrow" });
keyInputIncreaseVelocity.setSource("KeyInputButton.qml", { "text": "Down Arrow" });
keyInputPlayPause.setSource("KeyInputButton.qml", { "text": "Spacebar" });
keyInputMoveBackwards.setSource("KeyInputButton.qml", { "text": "Page Up" });
keyInputMoveForward.setSource("KeyInputButton.qml", { "text": "Page Down" });
keyInputTogglePrompter.setSource("KeyInputButton.qml", { "text": qmlutil.keyToString(prompter.keys.toggle, prompter.keys.toggleModifiers) });
keyInputDecreaseVelocity.setSource("KeyInputButton.qml", { "text": qmlutil.keyToString(prompter.keys.increaseVelocity, prompter.keys.increaseVelocityModifiers) });
keyInputIncreaseVelocity.setSource("KeyInputButton.qml", { "text": qmlutil.keyToString(prompter.keys.decreaseVelocity, prompter.keys.decreaseVelocityModifiers) });
keyInputPlayPause.setSource("KeyInputButton.qml", { "text": qmlutil.keyToString(prompter.keys.pause, prompter.keys.pauseModifiers) });
keyInputMoveBackwards.setSource("KeyInputButton.qml", { "text": qmlutil.keyToString(prompter.keys.skipBackwards, prompter.keys.skipBackwardsModifiers) });
keyInputMoveForward.setSource("KeyInputButton.qml", { "text": qmlutil.keyToString(prompter.keys.skipForward, prompter.keys.skipForwardModifiers) });
keyInputPreviousMarker.setSource("KeyInputButton.qml", { "text": qmlutil.keyToString(prompter.keys.previousMarker, prompter.keys.previousMarkerModifiers) });
keyInputNextMarker.setSource("KeyInputButton.qml", { "text": qmlutil.keyToString(prompter.keys.nextMarker, prompter.keys.nextMarkerModifiers) });
}
Connections {
target: keyInputTogglePrompter.item
function onToggleButtonsOff() { buttonGrid.toggleButtonsOff(); }
function onSetKey(key) { prompter.keys.toggle=key; }
function onSetKey(key, modifiers) {
prompter.keys.toggle = key;
prompter.keys.toggleModifiers = modifiers;
}
}
Connections {
target: keyInputDecreaseVelocity.item
function onToggleButtonsOff() { buttonGrid.toggleButtonsOff(); }
function onSetKey(key) { prompter.keys.decreaseVelocity = key; }
function onSetKey(key, modifiers) {
prompter.keys.decreaseVelocity = key;
prompter.keys.decreaseVelocityModifiers = modifiers;
}
}
Connections {
target: keyInputIncreaseVelocity.item
function onToggleButtonsOff() { buttonGrid.toggleButtonsOff(); }
function onSetKey(key) { prompter.keys.increaseVelocity = key; }
function onSetKey(key, modifiers) {
prompter.keys.increaseVelocity = key;
prompter.keys.increaseVelocityModifiers = modifiers;
}
}
Connections {
target: keyInputPlayPause.item
function onToggleButtonsOff() { buttonGrid.toggleButtonsOff(); }
function onSetKey(key) { prompter.keys.pause = key; }
function onSetKey(key, modifiers) {
prompter.keys.pause = key;
prompter.keys.pauseModifiers = modifiers;
}
}
Connections {
target: keyInputMoveBackwards.item
function onToggleButtonsOff() { buttonGrid.toggleButtonsOff(); }
function onSetKey(key) { prompter.keys.skipBackwards = key; }
function onSetKey(key, modifiers) {
prompter.keys.skipBackwards = key;
prompter.keys.skipBackwardsModifiers = modifiers;
}
}
Connections {
target: keyInputMoveForward.item
function onToggleButtonsOff() { buttonGrid.toggleButtonsOff(); }
function onSetKey(key) { prompter.keys.skipForward = key; }
function onSetKey(key, modifiers) {
prompter.keys.skipForward = key;
prompter.keys.skipForwardModifiers = modifiers;
}
}
Connections {
target: keyInputPreviousMarker.item
function onToggleButtonsOff() { buttonGrid.toggleButtonsOff(); }
function onSetKey(key, modifiers) {
prompter.keys.previousMarker = key;
prompter.keys.previousMarkerModifiers = modifiers;
}
}
Connections {
target: keyInputNextMarker.item
function onToggleButtonsOff() { buttonGrid.toggleButtonsOff(); }
function onSetKey(key, modifiers) {
prompter.keys.nextMarker = key;
prompter.keys.nextMarkerModifiers = modifiers;
}
}

Label {
Expand Down Expand Up @@ -137,23 +175,25 @@ Kirigami.OverlaySheet {
asynchronous: true
Layout.fillWidth: true
}
/*
Label {
text: i18n("Go to Previous Marker")
}
Loader {
id: keyInputHome
id: keyInputPreviousMarker
asynchronous: true
Layout.fillWidth: true
}
Label {
text: i18n("Go to Next Marker")
}
Loader {
id: keyInputEnd
id: keyInputNextMarker
asynchronous: true
Layout.fillWidth: true
}
*/

QmlUtil {
id: qmlutil
}
}
}
119 changes: 31 additions & 88 deletions src/kirigami_ui/KeyInputButton.qml
Expand Up @@ -23,97 +23,40 @@ import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12

import com.cuperino.qprompt.qmlutil 1.0

Button {
id: keyInputButton

signal toggleButtonsOff()
signal setKey(var key)
signal setKey(int key, int modifiers)

// Validate input
function isValidInput(input) {
function isValidInput(key, modifiers) {
const actions = [
[prompter.keys.increaseVelocity, prompter.keys.increaseVelocityModifiers],
[prompter.keys.decreaseVelocity, prompter.keys.decreaseVelocityModifiers],
[prompter.keys.pause, prompter.keys.pauseModifiers],
[prompter.keys.skipBackwards, prompter.keys.skipBackwardsModifiers],
[prompter.keys.skipForward, prompter.keys.skipForwardModifiers],
[prompter.keys.previousMarker, prompter.keys.previousMarkerModifiers],
[prompter.keys.nextMarker, prompter.keys.nextMarkerModifiers],
[prompter.keys.toggle, prompter.keys.toggleModifiers]
]
// Return invalid if key is in use
let flag = false;
Object.values(prompter.keys).every(assignedKey => {
flag = assignedKey===input;
return !flag;
});
return !flag && [Qt.Key_Escape, Qt.Key_Super_L, Qt.Key_Super_R, Qt.Key_Meta].indexOf(input)===-1
}
// Get key text
function getKeyText(event) {
let text = "";
switch (event.key) {
case Qt.Key_Escape: text = "ESC"; break;
case Qt.Key_Space: text = i18n("Spacebar"); break;
case Qt.Key_Up: text = i18n("Up Arrow"); break;
case Qt.Key_Down: text = i18n("Down Arrow"); break;
case Qt.Key_Left: text = i18n("Left Arrow"); break;
case Qt.Key_Right: text = i18n("Right Arrow"); break;
case Qt.Key_Tab: text = "Tab"; break;
case Qt.Key_Backtab: text = i18n("Backtab"); break;
case Qt.Key_PageUp: text = i18n("Page Up"); break;
case Qt.Key_PageDown: text = i18n("Page Down"); break;
case Qt.Key_Home: text = i18n("Home"); break;
case Qt.Key_End: text = i18n("End"); break;
case Qt.Key_Backspace: text = i18n("Backspace"); break;
case Qt.Key_Delete: text = i18n("Delete"); break;
case Qt.Key_Insert: text = i18n("Insert"); break;
case Qt.Key_Enter: text = i18n("Enter"); break;
case Qt.Key_Return: text = i18n("Enter"); break;
case Qt.Key_Control: text = Qt.platform.os==="osx" || Qt.platform.os==="ios" || Qt.platform.os==="tvos" || Qt.platform.os==="ipados" ? "Command" : "Control"; break;
case Qt.Key_Super_L: text = Qt.platform.os==="osx" || Qt.platform.os==="ios" || Qt.platform.os==="tvos" || Qt.platform.os==="ipados" ? i18n("Left %1", "Control") : (Qt.platform.os==="windows" || Qt.platform.os==="winrt" ? i18n("Left %1", "Windows") : (Qt.platform.os==="linux" || Qt.platform.os==="unix" ? i18n("Left %1", "Super") : i18n("Left %1", "Meta"))); break;
case Qt.Key_Super_R: text = Qt.platform.os==="osx" || Qt.platform.os==="ios" || Qt.platform.os==="tvos" || Qt.platform.os==="ipados" ? i18n("Right %1", "Control") : (Qt.platform.os==="windows" || Qt.platform.os==="winrt" ? i18n("Right %1", "Windows") : (Qt.platform.os==="linux" || Qt.platform.os==="unix" ? i18n("Right %1", "Super") : i18n("Right %1", "Meta"))); break;
case Qt.Key_Meta: text = Qt.platform.os==="osx" || Qt.platform.os==="ios" || Qt.platform.os==="tvos" || Qt.platform.os==="ipados" ? "Control" : (Qt.platform.os==="windows" || Qt.platform.os==="winrt" ? "Windows" : (Qt.platform.os==="linux" || Qt.platform.os==="unix" ? "Super" : "Meta")); break;
case Qt.Key_Alt: text = Qt.platform.os==="osx" ? "Option" : "Alt"; break;
case Qt.Key_AltGr: text = Qt.platform.os==="osx" ? "Option" : "AltGr"; break;
case Qt.Key_Shift: text = i18n("Shift"); break;
case Qt.Key_NumLock: text = i18n("Number Lock"); break;
case Qt.Key_CapsLock: text = i18n("Caps Lock"); break;
case Qt.Key_ScrollLock: text = i18n("Scroll Lock"); break;
case Qt.Key_F1: text = "F1"; break;
case Qt.Key_F2: text = "F2"; break;
case Qt.Key_F3: text = "F3"; break;
case Qt.Key_F4: text = "F4"; break;
case Qt.Key_F5: text = "F5"; break;
case Qt.Key_F6: text = "F6"; break;
case Qt.Key_F7: text = "F7"; break;
case Qt.Key_F8: text = "F8"; break;
case Qt.Key_F9: text = "F9"; break;
case Qt.Key_F10: text = "F10"; break;
case Qt.Key_F11: text = "F11"; break;
case Qt.Key_F12: text = "F12"; break;
case Qt.Key_F13: text = "F13"; break;
case Qt.Key_F14: text = "F14"; break;
case Qt.Key_F15: text = "F15"; break;
case Qt.Key_F16: text = "F16"; break;
case Qt.Key_F17: text = "F17"; break;
case Qt.Key_F18: text = "F18"; break;
case Qt.Key_F19: text = "F19"; break;
case Qt.Key_F20: text = "F20"; break;
case Qt.Key_F21: text = "F21"; break;
case Qt.Key_F22: text = "F22"; break;
case Qt.Key_F23: text = "F23"; break;
case Qt.Key_F24: text = "F24"; break;
case Qt.Key_F25: text = "F25"; break;
case Qt.Key_F26: text = "F26"; break;
case Qt.Key_F27: text = "F27"; break;
case Qt.Key_F28: text = "F28"; break;
case Qt.Key_F29: text = "F29"; break;
case Qt.Key_F30: text = "F30"; break;
case Qt.Key_F31: text = "F31"; break;
case Qt.Key_F32: text = "F32"; break;
case Qt.Key_F33: text = "F33"; break;
case Qt.Key_F34: text = "F34"; break;
case Qt.Key_F35: text = "F35"; break;
case Qt.Key_HomePage: text = i18n("Home Page"); break;
case Qt.Key_LaunchMail: text = "E-mail"; break;
case Qt.Key_Refresh: text = i18n("Refresh"); break;
case Qt.Key_Search: text = i18n("Search"); break;
case Qt.Key_Zoom: text = "Zoom"; break;
case Qt.Key_Print: text = i18n("Print"); break;
default:
text = event.text==="" ? event.key : event.text;
for (let i=0; i<actions.length; i++) {
if ( actions[i][0]===key && actions[i][1]===modifiers ) {
flag = true;
break;
}
}
return text
// The following inputs will not be considered valid on their own
return !flag && [Qt.Key_Escape, Qt.Key_Super_L, Qt.Key_Super_R, Qt.Key_Meta].indexOf(key)===-1
}

QmlUtil {
id: qmlutil
}

checkable: true
Expand All @@ -132,13 +75,13 @@ Button {
event.accepted = true
}
Keys.onPressed: {
if (checked) {
if (isValidInput(event.key)) {
keyInputButton.setKey(event.key);
text = getKeyText(event);
if (checked && [Qt.Key_Super_L, Qt.Key_Super_R, Qt.Key_Meta, Qt.Key_Control, Qt.Key_Shift, Qt.Key_Alt, Qt.Key_AltGr].indexOf(event.key)===-1) {
if (isValidInput(event.key, event.modifiers)) {
keyInputButton.setKey(event.key, event.modifiers);
text = qmlutil.keyToString(event.key, event.modifiers);
}
event.accepted = true;
keyInputButton.toggleButtonsOff();
}
keyInputButton.toggleButtonsOff();
}
}
19 changes: 7 additions & 12 deletions src/kirigami_ui/main.qml
Expand Up @@ -67,17 +67,6 @@ Kirigami.ApplicationWindow {
minimumWidth: Kirigami.Settings.isMobile ? 291 : 351
minimumHeight: minimumWidth

// Key bindings
Keys.onPressed: {
if (parseInt(prompter.state) === Prompter.States.Prompting)
switch (event.key) {
case Qt.Key_F11:
if (!root.fullScreenPlatform)
root.__fullScreen = !root.__fullScreen
return
}
}

Settings {
category: "mainWindow"
property alias x: root.x
Expand Down Expand Up @@ -312,7 +301,13 @@ Kirigami.ApplicationWindow {
// On ESC pressed, return to PrompterEdit mode.
Kirigami.Action {
visible: false
onTriggered: root.pageStack.currentItem.prompter.cancel()
onTriggered: {
// If Escape is pressed while prompting, return focus to prompter, thus leaving edit while prompting mode.
if (parseInt(root.pageStack.currentItem.prompter.state)===Prompter.States.Prompting && root.pageStack.currentItem.editor.focus)
root.pageStack.currentItem.prompter.focus = true;
else
root.pageStack.currentItem.prompter.cancel()
}
shortcut: StandardKey.Cancel
}
]
Expand Down
2 changes: 2 additions & 0 deletions src/main.cpp
Expand Up @@ -43,6 +43,7 @@

#include "../qprompt_version.h"
#include "prompter/documenthandler.h"
#include "qt/qmlutil.hpp"

#define QPROMPT_URI "com.cuperino.qprompt"

Expand Down Expand Up @@ -97,6 +98,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
//qmlRegisterType<PrompterTimer>(QPROMPT_URI + ".promptertimer", 1, 0, "PrompterTimer");
qmlRegisterType<DocumentHandler>(QPROMPT_URI".document", 1, 0, "DocumentHandler");
qmlRegisterType<MarkersModel>(QPROMPT_URI".markers", 1, 0, "MarkersModel");
qmlRegisterType<QmlUtil>(QPROMPT_URI".qmlutil", 1, 0, "QmlUtil");
qRegisterMetaType<Marker>();

QQmlApplicationEngine engine;
Expand Down

0 comments on commit bd8e2a9

Please sign in to comment.