load keyboard layouts on the server side
this means decoding a fairly large (40k) blob of JSON in the client, but it seems to be OK.
This commit is contained in:
parent
697949c1d2
commit
622aec8abf
|
@ -15,7 +15,6 @@ subiquity/client/controllers/ssh.py
|
|||
subiquity/client/controllers/welcome.py
|
||||
subiquity/client/controllers/zdev.py
|
||||
subiquity/client/__init__.py
|
||||
subiquity/client/keyboard.py
|
||||
subiquity/client/keycodes.py
|
||||
subiquity/cmd/common.py
|
||||
subiquity/cmd/__init__.py
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
import logging
|
||||
|
||||
from subiquity.client.controller import SubiquityTuiController
|
||||
from subiquity.client.keyboard import KeyboardList
|
||||
from subiquity.common.types import KeyboardSetting
|
||||
from subiquity.ui.views import KeyboardView
|
||||
|
||||
|
@ -28,29 +27,9 @@ class KeyboardController(SubiquityTuiController):
|
|||
|
||||
endpoint_name = 'keyboard'
|
||||
|
||||
signals = [
|
||||
('l10n:language-selected', 'language_selected'),
|
||||
]
|
||||
|
||||
def __init__(self, app):
|
||||
super().__init__(app)
|
||||
self.keyboard_list = KeyboardList()
|
||||
|
||||
def language_selected(self, code):
|
||||
log.debug("language_selected %s", code)
|
||||
if not self.keyboard_list.has_language(code):
|
||||
code = code.split('_')[0]
|
||||
if not self.keyboard_list.has_language(code):
|
||||
code = 'C'
|
||||
log.debug("loading language %s", code)
|
||||
self.keyboard_list.load_language(code)
|
||||
|
||||
async def make_ui(self):
|
||||
if self.keyboard_list.current_lang is None:
|
||||
self.keyboard_list.load_language('C')
|
||||
initial_setting = await self.endpoint.GET()
|
||||
view = KeyboardView(self, initial_setting)
|
||||
return view
|
||||
setup = await self.endpoint.GET()
|
||||
return KeyboardView(self, setup)
|
||||
|
||||
async def run_answers(self):
|
||||
if 'layout' in self.answers:
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
# Copyright 2020 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
|
||||
from subiquity.common.serialize import Serializer
|
||||
from subiquity.common.types import (
|
||||
KeyboardLayout,
|
||||
)
|
||||
|
||||
|
||||
class KeyboardList:
|
||||
|
||||
def __init__(self):
|
||||
self._kbnames_dir = os.path.join(os.environ.get("SNAP", '.'), 'kbds')
|
||||
self.serializer = Serializer(compact=True)
|
||||
self._clear()
|
||||
|
||||
def _file_for_lang(self, code):
|
||||
return os.path.join(self._kbnames_dir, code + '.jsonl')
|
||||
|
||||
def has_language(self, code):
|
||||
return os.path.exists(self._file_for_lang(code))
|
||||
|
||||
def load_language(self, code):
|
||||
if code == self.current_lang:
|
||||
return
|
||||
|
||||
self._clear()
|
||||
|
||||
with open(self._file_for_lang(code)) as kbdnames:
|
||||
self.layouts = [
|
||||
self.serializer.from_json(KeyboardLayout, line)
|
||||
for line in kbdnames
|
||||
]
|
||||
self.current_lang = code
|
||||
|
||||
def _clear(self):
|
||||
self.current_lang = None
|
||||
self.layouts = []
|
|
@ -29,6 +29,7 @@ from subiquity.common.types import (
|
|||
ApplicationStatus,
|
||||
ErrorReportRef,
|
||||
KeyboardSetting,
|
||||
KeyboardSetup,
|
||||
IdentityData,
|
||||
RefreshStatus,
|
||||
SnapInfo,
|
||||
|
@ -91,7 +92,7 @@ class API:
|
|||
def GET(change_id: str) -> dict: ...
|
||||
|
||||
class keyboard:
|
||||
def GET() -> KeyboardSetting: ...
|
||||
def GET() -> KeyboardSetup: ...
|
||||
def POST(data: Payload[KeyboardSetting]): ...
|
||||
|
||||
class needs_toggle:
|
||||
|
|
|
@ -137,6 +137,12 @@ class KeyboardLayout:
|
|||
variants: List[KeyboardVariant]
|
||||
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class KeyboardSetup:
|
||||
setting: KeyboardSetting
|
||||
layouts: List[KeyboardLayout]
|
||||
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class ZdevInfo:
|
||||
id: str
|
||||
|
|
|
@ -26,7 +26,9 @@ from subiquity.common.apidef import API
|
|||
from subiquity.common.serialize import Serializer
|
||||
from subiquity.common.types import (
|
||||
AnyStep,
|
||||
KeyboardLayout,
|
||||
KeyboardSetting,
|
||||
KeyboardSetup,
|
||||
)
|
||||
from subiquity.server.controller import SubiquityController
|
||||
|
||||
|
@ -112,6 +114,44 @@ def for_ui(setting):
|
|||
layout=layout, variant=variant, toggle=setting.toggle)
|
||||
|
||||
|
||||
class KeyboardList:
|
||||
|
||||
def __init__(self):
|
||||
self._kbnames_dir = os.path.join(os.environ.get("SNAP", '.'), 'kbds')
|
||||
self.serializer = Serializer(compact=True)
|
||||
self._clear()
|
||||
|
||||
def _file_for_lang(self, code):
|
||||
return os.path.join(self._kbnames_dir, code + '.jsonl')
|
||||
|
||||
def _has_language(self, code):
|
||||
return os.path.exists(self._file_for_lang(code))
|
||||
|
||||
def load_language(self, code):
|
||||
if '.' in code:
|
||||
code = code.split('.')[0]
|
||||
if not self._has_language(code):
|
||||
code = code.split('_')[0]
|
||||
if not self._has_language(code):
|
||||
code = 'C'
|
||||
|
||||
if code == self.current_lang:
|
||||
return
|
||||
|
||||
self._clear()
|
||||
|
||||
with open(self._file_for_lang(code)) as kbdnames:
|
||||
self.layouts = [
|
||||
self.serializer.from_json(KeyboardLayout, line)
|
||||
for line in kbdnames
|
||||
]
|
||||
self.current_lang = code
|
||||
|
||||
def _clear(self):
|
||||
self.current_lang = None
|
||||
self.layouts = []
|
||||
|
||||
|
||||
class KeyboardController(SubiquityController):
|
||||
|
||||
endpoint = API.keyboard
|
||||
|
@ -133,6 +173,7 @@ class KeyboardController(SubiquityController):
|
|||
self.serializer = Serializer(compact=True)
|
||||
self.pc105_steps = None
|
||||
self.needs_set_keyboard = False
|
||||
self.keyboard_list = KeyboardList()
|
||||
super().__init__(app)
|
||||
|
||||
def load_autoinstall_data(self, data):
|
||||
|
@ -166,8 +207,12 @@ class KeyboardController(SubiquityController):
|
|||
for cmd in cmds:
|
||||
await arun_command(cmd)
|
||||
|
||||
async def GET(self) -> KeyboardSetting:
|
||||
return for_ui(self.model.setting)
|
||||
async def GET(self) -> KeyboardSetup:
|
||||
self.keyboard_list.load_language(
|
||||
self.app.base_model.locale.selected_language)
|
||||
return KeyboardSetup(
|
||||
setting=for_ui(self.model.setting),
|
||||
layouts=self.keyboard_list.layouts)
|
||||
|
||||
async def POST(self, data: KeyboardSetting):
|
||||
new = latinizable(data.layout, data.variant)
|
||||
|
|
|
@ -360,21 +360,22 @@ class KeyboardView(BaseView):
|
|||
|
||||
title = _("Keyboard configuration")
|
||||
|
||||
def __init__(self, controller, setting):
|
||||
def __init__(self, controller, setup):
|
||||
self.controller = controller
|
||||
self.keyboard_list = controller.keyboard_list
|
||||
self.initial_setting = setting
|
||||
self.initial_setting = setup.setting
|
||||
self.layouts = setup.layouts
|
||||
|
||||
self.form = KeyboardForm()
|
||||
opts = []
|
||||
for layout in self.keyboard_list.layouts:
|
||||
for layout in self.layouts:
|
||||
opts.append(Option((layout.name, True, layout)))
|
||||
opts.sort(key=lambda o: locale.strxfrm(o.label.text))
|
||||
connect_signal(self.form, 'submit', self.done)
|
||||
connect_signal(self.form, 'cancel', self.cancel)
|
||||
connect_signal(self.form.layout.widget, "select", self.select_layout)
|
||||
self.form.layout.widget.options = opts
|
||||
layout, variant = self.lookup(setting.layout, setting.variant)
|
||||
layout, variant = self.lookup(
|
||||
setup.setting.layout, setup.setting.variant)
|
||||
self.set_values(layout, variant)
|
||||
|
||||
if self.controller.opts.run_on_serial:
|
||||
|
@ -448,7 +449,7 @@ class KeyboardView(BaseView):
|
|||
self.form.variant.enabled = len(opts) > 1
|
||||
|
||||
def lookup(self, layout_code, variant_code):
|
||||
for layout in self.keyboard_list.layouts:
|
||||
for layout in self.layouts:
|
||||
if layout.code == layout_code:
|
||||
break
|
||||
if layout.code == "us":
|
||||
|
|
Loading…
Reference in New Issue