keyboard layout fixed in vmenu.
This commit is contained in:
203
src/fenrirscreenreader/core/dynamicKeyboardLayoutMenu.py
Normal file
203
src/fenrirscreenreader/core/dynamicKeyboardLayoutMenu.py
Normal file
@@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import glob
|
||||
import os
|
||||
|
||||
from fenrirscreenreader.core import debug
|
||||
|
||||
|
||||
class DynamicKeyboardLayoutCommand:
|
||||
"""Dynamic command class for keyboard layout selection"""
|
||||
|
||||
def __init__(self, layoutName, layoutPath, env):
|
||||
self.layoutName = layoutName
|
||||
self.layoutPath = layoutPath
|
||||
# Extract just the base name without extension for comparison
|
||||
self.layoutBaseName = layoutName
|
||||
self.env = env
|
||||
|
||||
def initialize(self, environment):
|
||||
self.env = environment
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def get_description(self):
|
||||
return f"Set keyboard layout to {self.layoutName}"
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
settingsManager = self.env["runtime"]["SettingsManager"]
|
||||
currentLayout = settingsManager.get_setting(
|
||||
"keyboard", "keyboardLayout"
|
||||
)
|
||||
|
||||
# Check if already set (compare both full path and base name)
|
||||
currentBaseName = os.path.splitext(os.path.basename(currentLayout))[0] if currentLayout else ""
|
||||
if currentBaseName.lower() == self.layoutBaseName.lower() or currentLayout.lower() == self.layoutPath.lower():
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
f"Keyboard layout already set to {self.layoutName}"
|
||||
)
|
||||
return
|
||||
|
||||
# Set the new layout in the config file using full path
|
||||
try:
|
||||
# Update the setting in memory
|
||||
settingsManager.set_setting(
|
||||
"keyboard", "keyboardLayout", self.layoutPath
|
||||
)
|
||||
|
||||
# Save to the actual config file
|
||||
configFilePath = settingsManager.get_settings_file()
|
||||
settingsManager.save_settings(configFilePath)
|
||||
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
f"Keyboard layout set to {self.layoutName}. Please restart Fenrir for this change to take effect."
|
||||
)
|
||||
# Play accept sound
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"", sound_icon="Accept", interrupt=False
|
||||
)
|
||||
except Exception as e:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
f"Failed to change keyboard layout to {self.layoutName}"
|
||||
)
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
f"DynamicKeyboardLayout: Error setting layout {self.layoutName}: {e}",
|
||||
debug.DebugLevel.ERROR,
|
||||
)
|
||||
# Play error sound
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
"", sound_icon="ErrorSound", interrupt=False
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
self.env["runtime"]["OutputManager"].present_text(
|
||||
f"Keyboard layout change error: {str(e)}", interrupt=True
|
||||
)
|
||||
self.env["runtime"]["DebugManager"].write_debug_out(
|
||||
f"DynamicKeyboardLayout: Unexpected error for {self.layoutName}: {e}",
|
||||
debug.DebugLevel.ERROR,
|
||||
)
|
||||
|
||||
def set_callback(self, callback):
|
||||
pass
|
||||
|
||||
|
||||
def add_dynamic_keyboard_layout_menus(VmenuManager):
|
||||
"""Add dynamic keyboard layout menus to vmenu system"""
|
||||
try:
|
||||
env = VmenuManager.env
|
||||
|
||||
# Get keyboard layout files
|
||||
layouts = get_keyboard_layouts(env)
|
||||
if not layouts:
|
||||
return
|
||||
|
||||
# Create keyboard layouts submenu
|
||||
layoutMenu = {}
|
||||
|
||||
# Add layout commands
|
||||
for layoutName, layoutPath in layouts:
|
||||
layoutCommand = DynamicKeyboardLayoutCommand(
|
||||
layoutName, layoutPath, env
|
||||
)
|
||||
layoutMenu[f"{layoutName} Action"] = layoutCommand
|
||||
|
||||
# Find keyboard menu in existing vmenu structure
|
||||
# If fenrir menu exists, add layouts under it
|
||||
if "fenrir Menu" in VmenuManager.menuDict:
|
||||
fenrirMenu = VmenuManager.menuDict["fenrir Menu"]
|
||||
if "keyboard Menu" in fenrirMenu:
|
||||
# Add dynamic layouts to existing keyboard menu
|
||||
keyboardMenu = fenrirMenu["keyboard Menu"]
|
||||
keyboardMenu["Keyboard Layouts Menu"] = layoutMenu
|
||||
else:
|
||||
# Create keyboard menu with layouts
|
||||
fenrirMenu["keyboard Menu"] = {
|
||||
"Keyboard Layouts Menu": layoutMenu
|
||||
}
|
||||
else:
|
||||
# Create standalone keyboard layouts menu
|
||||
VmenuManager.menuDict["Keyboard Layouts Menu"] = layoutMenu
|
||||
|
||||
except Exception as e:
|
||||
# Use debug manager for error logging
|
||||
if "DebugManager" in env.get("runtime", {}):
|
||||
env["runtime"]["DebugManager"].write_debug_out(
|
||||
f"Error creating dynamic keyboard layout menus: {e}",
|
||||
debug.DebugLevel.ERROR,
|
||||
)
|
||||
else:
|
||||
print(f"Error creating dynamic keyboard layout menus: {e}")
|
||||
|
||||
|
||||
def get_keyboard_layouts(env):
|
||||
"""Get available keyboard layouts from keyboard directory"""
|
||||
layouts = []
|
||||
|
||||
try:
|
||||
# Get keyboard directory paths
|
||||
keyboardDirs = []
|
||||
|
||||
# Check system installation path
|
||||
systemKeyboardPath = "/etc/fenrirscreenreader/keyboard/"
|
||||
if os.path.exists(systemKeyboardPath):
|
||||
keyboardDirs.append(systemKeyboardPath)
|
||||
|
||||
# Check source/development path
|
||||
try:
|
||||
import fenrirscreenreader
|
||||
|
||||
fenrirPath = os.path.dirname(fenrirscreenreader.__file__)
|
||||
devKeyboardPath = os.path.join(
|
||||
fenrirPath, "..", "..", "config", "keyboard"
|
||||
)
|
||||
devKeyboardPath = os.path.abspath(devKeyboardPath)
|
||||
if os.path.exists(devKeyboardPath):
|
||||
keyboardDirs.append(devKeyboardPath)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Get current layout setting path
|
||||
try:
|
||||
currentLayoutSetting = env["runtime"]["SettingsManager"].get_setting(
|
||||
"keyboard", "keyboardLayout"
|
||||
)
|
||||
if currentLayoutSetting and os.path.exists(currentLayoutSetting):
|
||||
currentLayoutDir = os.path.dirname(currentLayoutSetting)
|
||||
if currentLayoutDir not in keyboardDirs:
|
||||
keyboardDirs.append(currentLayoutDir)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Scan for .conf files
|
||||
seenLayouts = set()
|
||||
for keyboardDir in keyboardDirs:
|
||||
try:
|
||||
confFiles = glob.glob(os.path.join(keyboardDir, "*.conf"))
|
||||
for confFile in confFiles:
|
||||
layoutName = os.path.splitext(os.path.basename(confFile))[
|
||||
0
|
||||
]
|
||||
if layoutName not in seenLayouts:
|
||||
seenLayouts.add(layoutName)
|
||||
layouts.append((layoutName, confFile))
|
||||
except Exception as e:
|
||||
if "DebugManager" in env.get("runtime", {}):
|
||||
env["runtime"]["DebugManager"].write_debug_out(
|
||||
f"Error scanning keyboard directory {keyboardDir}: {e}",
|
||||
debug.DebugLevel.WARNING,
|
||||
)
|
||||
|
||||
# Sort layouts alphabetically
|
||||
layouts.sort(key=lambda x: x[0].lower())
|
||||
|
||||
except Exception as e:
|
||||
if "DebugManager" in env.get("runtime", {}):
|
||||
env["runtime"]["DebugManager"].write_debug_out(
|
||||
f"Error getting keyboard layouts: {e}",
|
||||
debug.DebugLevel.ERROR,
|
||||
)
|
||||
|
||||
return layouts
|
||||
Reference in New Issue
Block a user