Files
noctalia-shell/Commons/Keybinds.qml
T

202 lines
5.6 KiB
QML

pragma Singleton
import QtQuick
QtObject {
function getKeybindString(event) {
let keyStr = "";
if (event.modifiers & Qt.ControlModifier)
keyStr += "Ctrl+";
if (event.modifiers & Qt.AltModifier)
keyStr += "Alt+";
if (event.modifiers & Qt.ShiftModifier)
keyStr += "Shift+";
let keyName = "";
let rawText = event.text;
if (event.key >= Qt.Key_A && event.key <= Qt.Key_Z || event.key >= Qt.Key_0 && event.key <= Qt.Key_9) {
keyName = String.fromCharCode(event.key);
} else if (event.key >= Qt.Key_F1 && event.key <= Qt.Key_F12) {
keyName = "F" + (event.key - Qt.Key_F1 + 1);
} else if (rawText && rawText.length > 0 && rawText.charCodeAt(0) > 31 && rawText.charCodeAt(0) !== 127) {
keyName = rawText.toUpperCase();
if (event.modifiers & Qt.ShiftModifier) {
const shiftMap = {
"!": "1",
"\"": "2",
"§": "3",
"$": "4",
"%": "5",
"&": "6",
"/": "7",
"(": "8",
")": "9",
"=": "0",
"@": "2",
"#": "3",
"^": "6",
"*": "8"
};
if (shiftMap[keyName]) {
keyName = shiftMap[keyName];
}
}
} else {
switch (event.key) {
case Qt.Key_Escape:
keyName = "Esc";
break;
case Qt.Key_Space:
keyName = "Space";
break;
case Qt.Key_Return:
keyName = "Return";
break;
case Qt.Key_Enter:
keyName = "Enter";
break;
case Qt.Key_Tab:
keyName = "Tab";
break;
case Qt.Key_Backspace:
keyName = "Backspace";
break;
case Qt.Key_Delete:
keyName = "Del";
break;
case Qt.Key_Insert:
keyName = "Ins";
break;
case Qt.Key_Home:
keyName = "Home";
break;
case Qt.Key_End:
keyName = "End";
break;
case Qt.Key_PageUp:
keyName = "PgUp";
break;
case Qt.Key_PageDown:
keyName = "PgDn";
break;
case Qt.Key_Left:
keyName = "Left";
break;
case Qt.Key_Right:
keyName = "Right";
break;
case Qt.Key_Up:
keyName = "Up";
break;
case Qt.Key_Down:
keyName = "Down";
break;
case Qt.Key_BracketLeft:
keyName = "[";
break;
case Qt.Key_BracketRight:
keyName = "]";
break;
case Qt.Key_Backslash:
keyName = "\\";
break;
case Qt.Key_Slash:
keyName = "/";
break;
case Qt.Key_QuoteLeft:
case Qt.Key_AsciiTilde:
case Qt.Key_Dead_Grave:
keyName = "`";
break;
}
}
if (!keyName)
return "";
return keyStr + keyName;
}
function checkKey(event, settingName, settings) {
// Accept both simplified names ("remove") and full property names ("keyRemove")
// so callers are less error-prone.
var normalized = String(settingName || "");
if (!normalized)
return false;
var propName = normalized.startsWith("key") ? normalized : ("key" + normalized.charAt(0).toUpperCase() + normalized.slice(1));
var boundKeys = settings.data.general.keybinds[propName];
if (!boundKeys || boundKeys.length === 0)
return false;
var eventString = getKeybindString(event);
for (var i = 0; i < boundKeys.length; i++) {
if (boundKeys[i] === eventString)
return true;
}
return false;
}
/**
* Check if a keybind string conflicts with any other existing keybinds.
* @param {string} keyStr - The keybind string to check (e.g., "Ctrl+A").
* @param {string} currentPath - The settings path of the keybind being edited (to skip checking itself).
* @param {object} data - The settings data object (from Settings.data).
* @returns {string|null} - The name of the conflicting action, or null if no conflict.
*/
function getKeybindConflict(keyStr, currentPath, data) {
if (!keyStr || !data)
return null;
const searchKey = String(keyStr).trim().toLowerCase();
// 1. Check navigation keybinds
const navKeybinds = data.general ? data.general.keybinds : null;
const navMap = {
"keyUp": "Navigation: Up",
"keyDown": "Navigation: Down",
"keyLeft": "Navigation: Left",
"keyRight": "Navigation: Right",
"keyEnter": "Navigation: Enter",
"keyEscape": "Navigation: Escape"
};
if (navKeybinds) {
for (const prop in navMap) {
const fullPath = "general.keybinds." + prop;
if (fullPath === currentPath)
continue;
const boundKeys = navKeybinds[prop];
if (boundKeys && boundKeys.length !== undefined) {
for (let i = 0; i < boundKeys.length; i++) {
if (String(boundKeys[i]).trim().toLowerCase() === searchKey) {
return navMap[prop];
}
}
}
}
}
// 2. Check session menu power options
const sessionMenu = data.sessionMenu;
if (sessionMenu && sessionMenu.powerOptions) {
const powerOptions = sessionMenu.powerOptions;
for (let i = 0; i < powerOptions.length; i++) {
const entry = powerOptions[i];
const fullPath = "sessionMenu.powerOptions[" + i + "].keybind";
if (fullPath === currentPath)
continue;
if (entry.keybind && String(entry.keybind).trim().toLowerCase() === searchKey) {
// Capitalize action name
const actionName = entry.action ? entry.action.charAt(0).toUpperCase() + entry.action.slice(1) : "Unknown";
return "Session Menu: " + actionName;
}
}
}
return null;
}
}