351 lines
12 KiB
Python
351 lines
12 KiB
Python
|
#
|
||
|
# Kickstart module for language and keyboard settings.
|
||
|
#
|
||
|
# Copyright (C) 2018 Red Hat, Inc.
|
||
|
#
|
||
|
# This copyrighted material is made available to anyone wishing to use,
|
||
|
# modify, copy, or redistribute it subject to the terms and conditions of
|
||
|
# the GNU General Public License v.2, or (at your option) any later version.
|
||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
# ANY WARRANTY expressed or implied, including the implied warranties of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||
|
# Public License for more details. You should have received a copy of the
|
||
|
# GNU General Public License along with this program; if not, write to the
|
||
|
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||
|
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
|
||
|
# source code or documentation are not subject to the GNU General Public
|
||
|
# License and may only be used or replicated with the express permission of
|
||
|
# Red Hat, Inc.
|
||
|
#
|
||
|
import langtable
|
||
|
|
||
|
from pyanaconda.core.configuration.anaconda import conf
|
||
|
from pyanaconda.core.dbus import DBus
|
||
|
from pyanaconda.core.signal import Signal
|
||
|
from pyanaconda.localization import get_available_translations, get_common_languages, \
|
||
|
get_english_name, get_language_locales, get_language_id, get_native_name
|
||
|
from pyanaconda.modules.common.base import KickstartService
|
||
|
from pyanaconda.modules.common.constants.services import LOCALIZATION
|
||
|
from pyanaconda.modules.common.containers import TaskContainer
|
||
|
from pyanaconda.modules.common.structures.language import LanguageData, LocaleData
|
||
|
from pyanaconda.modules.localization.localization_interface import LocalizationInterface
|
||
|
from pyanaconda.modules.localization.kickstart import LocalizationKickstartSpecification
|
||
|
from pyanaconda.modules.localization.installation import LanguageInstallationTask, \
|
||
|
KeyboardInstallationTask
|
||
|
from pyanaconda.modules.localization.runtime import GetMissingKeyboardConfigurationTask, \
|
||
|
ApplyKeyboardTask, AssignGenericKeyboardSettingTask
|
||
|
from pyanaconda.modules.localization.localed import LocaledWrapper
|
||
|
from pyanaconda.modules.localization.gk_keyboard_manager import GkKeyboardManager
|
||
|
|
||
|
from pyanaconda.anaconda_loggers import get_module_logger
|
||
|
log = get_module_logger(__name__)
|
||
|
|
||
|
|
||
|
class LocalizationService(KickstartService):
|
||
|
"""The Localization service."""
|
||
|
|
||
|
def __init__(self):
|
||
|
super().__init__()
|
||
|
self.language_changed = Signal()
|
||
|
self._language = ""
|
||
|
|
||
|
self.language_support_changed = Signal()
|
||
|
self._language_support = []
|
||
|
|
||
|
self.language_seen_changed = Signal()
|
||
|
self._language_seen = False
|
||
|
|
||
|
self.vc_keymap_changed = Signal()
|
||
|
self._vc_keymap = ""
|
||
|
|
||
|
self.x_layouts_changed = Signal()
|
||
|
self._x_layouts = []
|
||
|
|
||
|
self.switch_options_changed = Signal()
|
||
|
self._switch_options = []
|
||
|
|
||
|
self.keyboard_seen_changed = Signal()
|
||
|
self._keyboard_seen = False
|
||
|
|
||
|
self.compositor_selected_layout_changed = Signal()
|
||
|
self.compositor_layouts_changed = Signal()
|
||
|
|
||
|
self._localed_wrapper = None
|
||
|
self._compositor_keyboard_manager = None
|
||
|
|
||
|
def publish(self):
|
||
|
"""Publish the module."""
|
||
|
TaskContainer.set_namespace(LOCALIZATION.namespace)
|
||
|
DBus.publish_object(LOCALIZATION.object_path, LocalizationInterface(self))
|
||
|
DBus.register_service(LOCALIZATION.service_name)
|
||
|
|
||
|
@property
|
||
|
def kickstart_specification(self):
|
||
|
"""Return the kickstart specification."""
|
||
|
return LocalizationKickstartSpecification
|
||
|
|
||
|
def process_kickstart(self, data):
|
||
|
"""Process the kickstart data."""
|
||
|
# lang
|
||
|
self.set_language(data.lang.lang)
|
||
|
self.set_language_support(data.lang.addsupport)
|
||
|
|
||
|
self.set_language_seen(data.lang.seen)
|
||
|
|
||
|
# keyboard
|
||
|
self.set_vc_keymap(data.keyboard.vc_keymap)
|
||
|
self.set_x_layouts(data.keyboard.x_layouts)
|
||
|
self.set_switch_options(data.keyboard.switch_options)
|
||
|
|
||
|
if data.keyboard._keyboard:
|
||
|
self.set_from_generic_keyboard_setting(data.keyboard._keyboard)
|
||
|
|
||
|
self.set_keyboard_seen(data.keyboard.seen)
|
||
|
|
||
|
def setup_kickstart(self, data):
|
||
|
"""Set up the kickstart data."""
|
||
|
# lang
|
||
|
data.lang.lang = self.language
|
||
|
data.lang.addsupport = self.language_support
|
||
|
|
||
|
# keyboard
|
||
|
data.keyboard.vc_keymap = self.vc_keymap
|
||
|
data.keyboard.x_layouts = self.x_layouts
|
||
|
data.keyboard.switch_options = self.switch_options
|
||
|
|
||
|
def get_languages(self):
|
||
|
"""Get languages with available translations.
|
||
|
|
||
|
For example: ["en", "cs"]
|
||
|
|
||
|
:return: a list of language ids
|
||
|
"""
|
||
|
return get_available_translations()
|
||
|
|
||
|
def get_language_data(self, language_id):
|
||
|
"""Get data about the specified language.
|
||
|
|
||
|
:param: a language id (for example, "en")
|
||
|
:return: a language data
|
||
|
"""
|
||
|
tdata = LanguageData()
|
||
|
tdata.english_name = get_english_name(language_id)
|
||
|
tdata.is_common = language_id in get_common_languages()
|
||
|
tdata.language_id = language_id
|
||
|
tdata.native_name = get_native_name(language_id)
|
||
|
|
||
|
return tdata
|
||
|
|
||
|
def get_locales(self, language_id):
|
||
|
"""Get locales available for the specified language.
|
||
|
|
||
|
For example: ["de_DE.UTF-8", "de_AT.UTF-8", ... ]
|
||
|
|
||
|
:return: a list of locale ids
|
||
|
"""
|
||
|
return get_language_locales(language_id)
|
||
|
|
||
|
def get_common_locales(self):
|
||
|
"""Get a list of the most commonly used locales.
|
||
|
|
||
|
For example: ["ar_EG.UTF-8", "en_US.UTF-8", "en_GB.UTF-8", ...]
|
||
|
|
||
|
:return: a list of common locale IDs
|
||
|
"""
|
||
|
return langtable.list_common_locales()
|
||
|
|
||
|
def get_locale_data(self, locale_id):
|
||
|
"""Get data about the specified locale.
|
||
|
|
||
|
:param: a locale id (for example, "en_US.UTF-8")
|
||
|
:return: a locale data
|
||
|
"""
|
||
|
tdata = LocaleData()
|
||
|
tdata.english_name = get_english_name(locale_id)
|
||
|
tdata.language_id = get_language_id(locale_id)
|
||
|
tdata.locale_id = locale_id
|
||
|
tdata.native_name = get_native_name(locale_id)
|
||
|
|
||
|
return tdata
|
||
|
|
||
|
@property
|
||
|
def language(self):
|
||
|
"""Return the language."""
|
||
|
return self._language
|
||
|
|
||
|
def set_language(self, language):
|
||
|
"""Set the language."""
|
||
|
self._language = language
|
||
|
self.language_changed.emit()
|
||
|
log.debug("Language is set to %s.", language)
|
||
|
|
||
|
@property
|
||
|
def language_support(self):
|
||
|
"""Return suppored languages."""
|
||
|
return self._language_support
|
||
|
|
||
|
def set_language_support(self, language_support):
|
||
|
"""Set supported languages."""
|
||
|
self._language_support = language_support
|
||
|
self.language_support_changed.emit()
|
||
|
log.debug("Language support is set to %s.", language_support)
|
||
|
|
||
|
@property
|
||
|
def language_seen(self):
|
||
|
"""Was language command seen in kickstart?"""
|
||
|
return self._language_seen
|
||
|
|
||
|
def set_language_seen(self, seen):
|
||
|
"""Set whether language command was seen in kickstart."""
|
||
|
self._language_seen = seen
|
||
|
self.language_seen_changed.emit()
|
||
|
log.debug("Language seen set to %s.", seen)
|
||
|
|
||
|
@property
|
||
|
def vc_keymap(self):
|
||
|
"""Return virtual console keymap."""
|
||
|
return self._vc_keymap
|
||
|
|
||
|
def set_vc_keymap(self, vc_keymap):
|
||
|
"""Set virtual console keymap."""
|
||
|
self._vc_keymap = vc_keymap
|
||
|
self.vc_keymap_changed.emit()
|
||
|
log.debug("Virtual console keymap is set to %s.", vc_keymap)
|
||
|
|
||
|
@property
|
||
|
def x_layouts(self):
|
||
|
"""Return X Keyboard Layouts."""
|
||
|
return self._x_layouts
|
||
|
|
||
|
def set_x_layouts(self, x_layouts):
|
||
|
"""Set X Keyboard Layouts."""
|
||
|
self._x_layouts = x_layouts
|
||
|
self.x_layouts_changed.emit()
|
||
|
log.debug("X Layouts are set to %s.", x_layouts)
|
||
|
|
||
|
@property
|
||
|
def switch_options(self):
|
||
|
"""Return X layout switching options."""
|
||
|
return self._switch_options
|
||
|
|
||
|
def set_switch_options(self, switch_options):
|
||
|
"""Set X layout switching options."""
|
||
|
self._switch_options = switch_options
|
||
|
self.switch_options_changed.emit()
|
||
|
log.debug("X layout switch options are set to %s.", switch_options)
|
||
|
|
||
|
@property
|
||
|
def keyboard_seen(self):
|
||
|
"""Was keyboard command seen in kickstart?"""
|
||
|
return self._keyboard_seen
|
||
|
|
||
|
def set_keyboard_seen(self, keyboard_seen):
|
||
|
"""Set whether keyboard command was seen in kickstart."""
|
||
|
self._keyboard_seen = keyboard_seen
|
||
|
self.keyboard_seen_changed.emit()
|
||
|
log.debug("keyboard command considered seen in kicksatart: %s.", keyboard_seen)
|
||
|
|
||
|
@property
|
||
|
def localed_wrapper(self):
|
||
|
if not self._localed_wrapper:
|
||
|
self._localed_wrapper = LocaledWrapper()
|
||
|
return self._localed_wrapper
|
||
|
|
||
|
def install_with_tasks(self):
|
||
|
"""Return the installation tasks of this module.
|
||
|
|
||
|
:returns: list of installation tasks
|
||
|
"""
|
||
|
return [
|
||
|
LanguageInstallationTask(
|
||
|
sysroot=conf.target.system_root,
|
||
|
lang=self.language
|
||
|
),
|
||
|
KeyboardInstallationTask(
|
||
|
sysroot=conf.target.system_root,
|
||
|
localed_wrapper=self.localed_wrapper,
|
||
|
x_layouts=self.x_layouts,
|
||
|
switch_options=self.switch_options,
|
||
|
vc_keymap=self.vc_keymap
|
||
|
)
|
||
|
]
|
||
|
|
||
|
def populate_missing_keyboard_configuration_with_task(self):
|
||
|
"""Populate missing keyboard configuration.
|
||
|
|
||
|
The configuration is populated by conversion and/or default values.
|
||
|
|
||
|
:returns: a task getting missing keyboard configuration
|
||
|
"""
|
||
|
task = GetMissingKeyboardConfigurationTask(
|
||
|
localed_wrapper=self.localed_wrapper,
|
||
|
x_layouts=self.x_layouts,
|
||
|
vc_keymap=self.vc_keymap,
|
||
|
)
|
||
|
task.succeeded_signal.connect(lambda: self._update_settings_from_task(task.get_result()))
|
||
|
return task
|
||
|
|
||
|
def _update_settings_from_task(self, result):
|
||
|
"""Update settings from task result."""
|
||
|
x_layouts, vc_keymap = result
|
||
|
self.set_vc_keymap(vc_keymap)
|
||
|
self.set_x_layouts(x_layouts)
|
||
|
|
||
|
def apply_keyboard_with_task(self):
|
||
|
"""Apply keyboard configuration to the current system.
|
||
|
|
||
|
:returns: a task applying the configuration
|
||
|
"""
|
||
|
task = ApplyKeyboardTask(
|
||
|
localed_wrapper=self.localed_wrapper,
|
||
|
x_layouts=self.x_layouts,
|
||
|
vc_keymap=self.vc_keymap,
|
||
|
switch_options=self.switch_options
|
||
|
)
|
||
|
task.succeeded_signal.connect(lambda: self._update_settings_from_task(task.get_result()))
|
||
|
return task
|
||
|
|
||
|
def set_from_generic_keyboard_setting(self, keyboard):
|
||
|
"""Set keyboard from generic keyboard setting
|
||
|
|
||
|
:param keyboard:
|
||
|
"""
|
||
|
log.debug("Setting keyboard from generic setting value '%s'.", keyboard)
|
||
|
if self.vc_keymap or self.x_layouts:
|
||
|
log.debug("Ignoring generic keyboard setting as we have a specific one.")
|
||
|
return
|
||
|
|
||
|
task = AssignGenericKeyboardSettingTask(
|
||
|
keyboard=keyboard
|
||
|
)
|
||
|
result = task.run()
|
||
|
self._update_settings_from_task(result)
|
||
|
|
||
|
@property
|
||
|
def compositor_keyboard_manager(self):
|
||
|
if not self._compositor_keyboard_manager:
|
||
|
self._compositor_keyboard_manager = GkKeyboardManager()
|
||
|
self._compositor_keyboard_manager.compositor_selected_layout_changed.connect(
|
||
|
lambda layout: self.compositor_selected_layout_changed.emit(layout)
|
||
|
)
|
||
|
self._compositor_keyboard_manager.compositor_layouts_changed.connect(
|
||
|
lambda layouts: self.compositor_layouts_changed.emit(layouts)
|
||
|
)
|
||
|
|
||
|
return self._compositor_keyboard_manager
|
||
|
|
||
|
def get_compositor_selected_layout(self):
|
||
|
return self.compositor_keyboard_manager.get_compositor_selected_layout()
|
||
|
|
||
|
def set_compositor_selected_layout(self, layout_variant):
|
||
|
return self.compositor_keyboard_manager.set_compositor_selected_layout(layout_variant)
|
||
|
|
||
|
def select_next_compositor_layout(self):
|
||
|
return self.compositor_keyboard_manager.select_next_compositor_layout()
|
||
|
|
||
|
def get_compositor_layouts(self):
|
||
|
return self.compositor_keyboard_manager.get_compositor_layouts()
|
||
|
|
||
|
def set_compositor_layouts(self, layout_variants, options):
|
||
|
self.compositor_keyboard_manager.set_compositor_layouts(layout_variants, options)
|