Skip to content

Commit

Permalink
Creating a dbus interface to get local keyboard layouts
Browse files Browse the repository at this point in the history
Adding dbus interface for loading locale keyboards

Remove duplicate function and migrate to localization one
  • Loading branch information
adamkankovsky committed Jan 16, 2025
1 parent 15ff849 commit efd8ae2
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 22 deletions.
31 changes: 30 additions & 1 deletion pyanaconda/localization.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@
import re
from collections import namedtuple

import iso639
import langtable
from xkbregistry import rxkb

from pyanaconda.anaconda_loggers import get_module_logger
from pyanaconda.core import constants
Expand All @@ -36,7 +38,7 @@
log = get_module_logger(__name__)

SCRIPTS_SUPPORTED_BY_CONSOLE = {'Latn', 'Cyrl', 'Grek'}

LayoutInfo = namedtuple("LayoutInfo", ["langs", "desc"])

class LocalizationConfigError(Exception):
"""Exception class for localization configuration related problems"""
Expand Down Expand Up @@ -390,6 +392,33 @@ def get_territory_locales(territory):
return langtable.list_locales(territoryId=territory)


def _build_layout_infos():
"""Build localized information for keyboard layouts.
:param rxkb_context: RXKB context (e.g., rxkb.Context())
:return: Dictionary with layouts and their descriptions
"""
rxkb_context = rxkb.Context()
layout_infos = {}

for layout in rxkb_context.layouts.values():
name = layout.name
if layout.variant:
name += f" ({layout.variant})"

langs = []
for lang in layout.iso639_codes:
if iso639.find(iso639_2=lang):
langs.append(iso639.to_name(lang))

if name not in layout_infos:
layout_infos[name] = LayoutInfo(langs, layout.description)
else:
layout_infos[name].langs.extend(langs)

return layout_infos


def get_locale_keyboards(locale):
"""Function returning preferred keyboard layouts for the given locale.
Expand Down
26 changes: 26 additions & 0 deletions pyanaconda/modules/localization/localization.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
import gettext
import langtable

from pyanaconda.anaconda_loggers import get_module_logger
from pyanaconda.core.configuration.anaconda import conf
from pyanaconda.core.dbus import DBus
from pyanaconda.core.signal import Signal
from pyanaconda.localization import (
_build_layout_infos,
get_available_translations,
get_common_languages,
get_english_name,
Expand All @@ -50,6 +52,8 @@

log = get_module_logger(__name__)

Xkb_ = lambda x: gettext.translation("xkeyboard-config", fallback=True).gettext(x)
iso_ = lambda x: gettext.translation("iso_639", fallback=True).gettext(x)

class LocalizationService(KickstartService):
"""The Localization service."""
Expand Down Expand Up @@ -80,6 +84,8 @@ def __init__(self):
self.compositor_selected_layout_changed = Signal()
self.compositor_layouts_changed = Signal()

self._layout_infos = _build_layout_infos()

self._localed_wrapper = None

def publish(self):
Expand Down Expand Up @@ -177,6 +183,26 @@ def get_locale_data(self, locale_id):

return tdata

def get_locale_keyboard_layouts(self, lang):
"""Get localized keyboard layouts for a given locale.
:param lang: locale string (e.g., "cs_CZ.UTF-8")
:return: list of dictionaries with keyboard layout information
"""
language_id = lang.split("_")[0].lower()
english_name = get_english_name(language_id)

return [
{
"layoutId": name,
"description": f"{Xkb_(info.desc)}",
"langs": info.langs,
}
# Include only the layouts of the current language in this structure
for name, info in self._layout_infos.items()
if english_name in info.langs
]

@property
def language(self):
"""Return the language."""
Expand Down
13 changes: 13 additions & 0 deletions pyanaconda/modules/localization/localization_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,19 @@ def GetLocaleData(self, locale_id: Str) -> Structure:
locale_data = self.implementation.get_locale_data(locale_id)
return LocaleData.to_structure(locale_data)

def GetLocaleKeyboardLayouts(self, lang: Str) -> List[Structure]:
"""Get keyboard layouts for the specified language.
For example: [
{"description": "US layout", "layoutId": "us", "variantId": ""},
{"description": "Czech QWERTY", "layoutId": "cz", "variantId": "qwerty"}
]
:param lang: Language code string (e.g., "en_US.UTF-8")
:return: List of keyboard layout dictionaries
"""
return self.implementation.get_locale_keyboard_layouts(lang)

@property
def Language(self) -> Str:
"""The language the system will use."""
Expand Down
23 changes: 2 additions & 21 deletions pyanaconda/ui/gui/xkl_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,19 @@

import gettext
import threading
from collections import namedtuple

import iso639
from xkbregistry import rxkb

from pyanaconda import localization
from pyanaconda.core.async_utils import async_action_wait
from pyanaconda.core.string import upcase_first_letter
from pyanaconda.keyboard import normalize_layout_variant
from pyanaconda.localization import _build_layout_infos
from pyanaconda.modules.common.constants.services import LOCALIZATION

Xkb_ = lambda x: gettext.translation("xkeyboard-config", fallback=True).gettext(x)
iso_ = lambda x: gettext.translation("iso_639", fallback=True).gettext(x)

# namedtuple for information about a keyboard layout (its language and description)
LayoutInfo = namedtuple("LayoutInfo", ["langs", "desc"])

class XklWrapper:
"""
Class that used to wrap libxklavier functionality.
Expand Down Expand Up @@ -62,26 +58,11 @@ def __init__(self):
self._rxkb = rxkb.Context()

self._layout_infos = {}
self._build_layout_infos()
self._layout_infos = _build_layout_infos()

self._switch_opt_infos = {}
self._build_switch_opt_infos()

def _build_layout_infos(self):
for layout in self._rxkb.layouts.values():
name = layout.name
if layout.variant:
name += ' (' + layout.variant + ')'

langs = []
for lang in layout.iso639_codes:
if iso639.find(iso639_2=lang):
langs.append(iso639.to_name(lang))

if name not in self._layout_infos:
self._layout_infos[name] = LayoutInfo(langs, layout.description)
else:
self._layout_infos[name].langs.extend(langs)

def _build_switch_opt_infos(self):
for group in self._rxkb.option_groups:
Expand Down

0 comments on commit efd8ae2

Please sign in to comment.