1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-06 05:25:41 -05:00
Files
DankMaterialShell/quickshell/Modules/DankBar/Widgets/KeyboardLayoutName.qml
2025-11-27 10:53:37 -05:00

196 lines
8.6 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Hyprland
import qs.Common
import qs.Modules.Plugins
import qs.Services
import qs.Widgets
BasePill {
id: root
property var widgetData: null
property bool compactMode: widgetData?.keyboardLayoutNameCompactMode !== undefined ? widgetData.keyboardLayoutNameCompactMode : SettingsData.keyboardLayoutNameCompactMode
readonly property var langCodes: ({
"afrikaans": "af", "albanian": "sq", "amharic": "am", "arabic": "ar",
"armenian": "hy", "azerbaijani": "az", "basque": "eu", "belarusian": "be",
"bengali": "bn", "bosnian": "bs", "bulgarian": "bg", "burmese": "my",
"catalan": "ca", "chinese": "zh", "croatian": "hr", "czech": "cs",
"danish": "da", "dutch": "nl", "english": "en", "esperanto": "eo",
"estonian": "et", "filipino": "fil", "finnish": "fi", "french": "fr",
"galician": "gl", "georgian": "ka", "german": "de", "greek": "el",
"gujarati": "gu", "hausa": "ha", "hebrew": "he", "hindi": "hi",
"hungarian": "hu", "icelandic": "is", "igbo": "ig", "indonesian": "id",
"irish": "ga", "italian": "it", "japanese": "ja", "javanese": "jv",
"kannada": "kn", "kazakh": "kk", "khmer": "km", "korean": "ko",
"kurdish": "ku", "kyrgyz": "ky", "lao": "lo", "latvian": "lv",
"lithuanian": "lt", "luxembourgish": "lb", "macedonian": "mk", "malay": "ms",
"malayalam": "ml", "maltese": "mt", "maori": "mi", "marathi": "mr",
"mongolian": "mn", "nepali": "ne", "norwegian": "no", "pashto": "ps",
"persian": "fa", "iranian": "fa", "farsi": "fa", "polish": "pl",
"portuguese": "pt", "punjabi": "pa", "romanian": "ro", "russian": "ru",
"serbian": "sr", "sindhi": "sd", "sinhala": "si", "slovak": "sk",
"slovenian": "sl", "somali": "so", "spanish": "es", "swahili": "sw",
"swedish": "sv", "tajik": "tg", "tamil": "ta", "tatar": "tt",
"telugu": "te", "thai": "th", "tibetan": "bo", "turkish": "tr",
"turkmen": "tk", "ukrainian": "uk", "urdu": "ur", "uyghur": "ug",
"uzbek": "uz", "vietnamese": "vi", "welsh": "cy", "yiddish": "yi",
"yoruba": "yo", "zulu": "zu"
})
readonly property var validVariants: ["US", "UK", "GB", "AZERTY", "QWERTY", "Dvorak", "Colemak", "Mac", "Intl", "International"]
property string currentLayout: {
if (CompositorService.isNiri) {
return NiriService.getCurrentKeyboardLayoutName();
} else if (CompositorService.isDwl) {
return DwlService.currentKeyboardLayout;
}
return "";
}
property string hyprlandKeyboard: ""
content: Component {
Item {
implicitWidth: root.isVerticalOrientation ? (root.widgetThickness - root.horizontalPadding * 2) : contentRow.implicitWidth
implicitHeight: root.isVerticalOrientation ? contentColumn.implicitHeight : (root.widgetThickness - root.horizontalPadding * 2)
Column {
id: contentColumn
visible: root.isVerticalOrientation
anchors.centerIn: parent
spacing: 1
DankIcon {
name: "keyboard"
size: Theme.barIconSize(root.barThickness)
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
StyledText {
text: {
if (!root.currentLayout)
return "";
const lang = root.currentLayout.split(" ")[0].toLowerCase();
const code = root.langCodes[lang] || lang.substring(0, 2);
return code.toUpperCase();
}
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale)
color: Theme.widgetTextColor
anchors.horizontalCenter: parent.horizontalCenter
}
}
Row {
id: contentRow
visible: !root.isVerticalOrientation
anchors.centerIn: parent
spacing: Theme.spacingS
StyledText {
text: {
if (!root.currentLayout)
return "";
if (root.compactMode && !CompositorService.isHyprland) {
const match = root.currentLayout.match(/^(\S+)(?:.*\(([^)]+)\))?/);
if (match) {
const lang = match[1].toLowerCase();
const code = root.langCodes[lang] || lang.substring(0, 2);
if (match[2]) {
const variant = match[2].trim();
const isValid = root.validVariants.some(v => variant.toUpperCase().includes(v.toUpperCase())) || variant.length <= 3;
if (isValid)
return code + "-" + variant;
}
return code.toUpperCase();
}
return root.currentLayout.substring(0, 2).toUpperCase();
}
return root.currentLayout;
}
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale)
color: Theme.widgetTextColor
anchors.verticalCenter: parent.verticalCenter
}
}
}
}
MouseArea {
z: 1
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
if (CompositorService.isNiri) {
NiriService.cycleKeyboardLayout();
} else if (CompositorService.isHyprland) {
Quickshell.execDetached(["hyprctl", "switchxkblayout", root.hyprlandKeyboard, "next"]);
} else if (CompositorService.isDwl) {
Quickshell.execDetached(["mmsg", "-d", "switch_keyboard_layout"]);
}
}
}
Connections {
target: CompositorService.isHyprland ? Hyprland : null
enabled: CompositorService.isHyprland
function onRawEvent(event) {
if (event.name === "activelayout") {
updateLayout();
}
}
}
Component.onCompleted: {
if (CompositorService.isHyprland) {
updateLayout();
}
}
function updateLayout() {
if (CompositorService.isHyprland) {
Proc.runCommand(null, ["hyprctl", "-j", "devices"], (output, exitCode) => {
if (exitCode !== 0) {
root.currentLayout = "Unknown";
return;
}
try {
const data = JSON.parse(output);
const mainKeyboard = data.keyboards.find(kb => kb.main === true);
root.hyprlandKeyboard = mainKeyboard.name;
if (mainKeyboard) {
const layout = mainKeyboard.layout;
const variant = mainKeyboard.variant;
const index = mainKeyboard.active_layout_index;
if (root.compactMode && layout && variant && index !== undefined) {
const layouts = mainKeyboard.layout.split(",");
const variants = mainKeyboard.variant.split(",");
const index = mainKeyboard.active_layout_index;
if (layouts[index] && variants[index] !== undefined) {
if (variants[index] === "") {
root.currentLayout = layouts[index];
} else {
root.currentLayout = layouts[index] + "-" + variants[index];
}
} else {
root.currentLayout = "Unknown";
}
} else if (mainKeyboard && mainKeyboard.active_keymap) {
root.currentLayout = mainKeyboard.active_keymap;
} else {
root.currentLayout = "Unknown";
}
} else {
root.currentLayout = "Unknown";
}
} catch (e) {
root.currentLayout = "Unknown";
}
});
}
}
}