locale - let it check interactive-sections again (#937)

* locale - let it check interactive-sections again

* Turn Serial into a whole new screen

When in serial, first offer the rich/basic choice (or SSH button),
and only show the current welcome screen if we choose rich mode.
Add a back button on Welcome if we are on serial.

LP: #1919251
This commit is contained in:
Dan Bungert 2021-04-21 10:11:27 -06:00 committed by GitHub
parent 046949f087
commit 2719c57c1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 156 additions and 77 deletions

View File

@ -93,6 +93,7 @@ class SubiquityClient(TuiApplication):
return SubiquityUI(self, self.help_menu) return SubiquityUI(self, self.help_menu)
controllers = [ controllers = [
"Serial",
"Welcome", "Welcome",
"Refresh", "Refresh",
"Keyboard", "Keyboard",

View File

@ -22,11 +22,13 @@ from .network import NetworkController
from .progress import ProgressController from .progress import ProgressController
from .proxy import ProxyController from .proxy import ProxyController
from .refresh import RefreshController from .refresh import RefreshController
from .serial import SerialController
from .snaplist import SnapListController from .snaplist import SnapListController
from .ssh import SSHController from .ssh import SSHController
from .welcome import WelcomeController from .welcome import WelcomeController
from .zdev import ZdevController from .zdev import ZdevController
# see SubiquityClient.controllers for another list
__all__ = [ __all__ = [
'FilesystemController', 'FilesystemController',
'IdentityController', 'IdentityController',
@ -37,6 +39,7 @@ __all__ = [
'ProxyController', 'ProxyController',
'RefreshController', 'RefreshController',
'RepeatedController', 'RepeatedController',
'SerialController',
'SnapListController', 'SnapListController',
'SSHController', 'SSHController',
'WelcomeController', 'WelcomeController',

View File

@ -0,0 +1,39 @@
# Copyright 2021 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 logging
from subiquity.client.controller import SubiquityTuiController
from subiquity.ui.views.serial import SerialView
from subiquitycore.tuicontroller import Skip
log = logging.getLogger('subiquity.client.controllers.serial')
class SerialController(SubiquityTuiController):
async def make_ui(self):
if not self.app.opts.run_on_serial:
raise Skip()
ssh_info = await self.app.client.meta.ssh_info.GET()
return SerialView(self, ssh_info)
def done(self, rich):
log.debug("SerialController.done rich %s next_screen", rich)
self.app.set_rich(rich)
self.app.next_screen()
def cancel(self):
# Can't go back from here!
pass

View File

@ -16,6 +16,7 @@
import logging import logging
from subiquitycore import i18n from subiquitycore import i18n
from subiquitycore.tuicontroller import Skip
from subiquity.client.controller import SubiquityTuiController from subiquity.client.controller import SubiquityTuiController
from subiquity.ui.views.welcome import WelcomeView from subiquity.ui.views.welcome import WelcomeView
@ -27,14 +28,12 @@ class WelcomeController(SubiquityTuiController):
endpoint_name = 'locale' endpoint_name = 'locale'
async def make_ui(self): async def make_ui(self):
if not self.app.rich_mode:
raise Skip()
language = await self.endpoint.GET() language = await self.endpoint.GET()
i18n.switch_language(language) i18n.switch_language(language)
serial = self.app.opts.run_on_serial self.serial = self.app.opts.run_on_serial
if serial: return WelcomeView(self, language, self.serial)
ssh_info = await self.app.client.meta.ssh_info.GET()
else:
ssh_info = None
return WelcomeView(self, language, serial, ssh_info)
def run_answers(self): def run_answers(self):
if 'lang' in self.answers: if 'lang' in self.answers:
@ -45,6 +44,8 @@ class WelcomeController(SubiquityTuiController):
i18n.switch_language(code) i18n.switch_language(code)
self.app.next_screen(self.endpoint.POST(code)) self.app.next_screen(self.endpoint.POST(code))
def cancel(self): def cancel(self, sender=None):
# Can't go back from here! if not self.serial:
# Can't go back from here unless we're on serial!
pass pass
self.app.prev_screen()

View File

@ -31,9 +31,6 @@ class LocaleController(SubiquityController):
autoinstall_schema = {'type': 'string'} autoinstall_schema = {'type': 'string'}
autoinstall_default = 'en_US.UTF-8' autoinstall_default = 'en_US.UTF-8'
def interactive(self):
return self.app.interactive
def load_autoinstall_data(self, data): def load_autoinstall_data(self, data):
os.environ["LANG"] = data os.environ["LANG"] = data

View File

@ -0,0 +1,89 @@
# Copyright 2021 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/>.
"""Welcome
Welcome provides user with language selection
"""
import logging
from urwid import Text
from subiquitycore.ui.buttons import forward_btn, other_btn
from subiquitycore.ui.utils import rewrap, screen
from subiquitycore.view import BaseView
log = logging.getLogger("subiquity.views.serial")
SERIAL_TEXT = """
As the installer is running on a serial console, it has started in
basic mode, using only the ASCII character set and black and white
colours.
If you are connecting from a terminal emulator such as gnome-terminal
that supports unicode and rich colours you can switch to "rich mode"
which uses unicode, colours and supports many languages.
"""
SSH_TEXT = """
You can also connect to the installer over the network via SSH, which
will allow use of rich mode.
"""
class SerialView(BaseView):
title = "Serial"
def __init__(self, controller, ssh_info):
self.controller = controller
self.ssh_info = ssh_info
super().__init__(self.make_serial())
def make_serial(self):
btns = [
forward_btn(
label="Continue in rich mode",
on_press=self.rich_mode),
forward_btn(
label="Continue in basic mode",
on_press=self.basic_mode),
]
widgets = [
Text(""),
Text(rewrap(SERIAL_TEXT)),
Text(""),
]
if self.ssh_info:
widgets.append(Text(rewrap(SSH_TEXT)))
widgets.append(Text(""))
btns.append(other_btn(
label="View SSH instructions",
on_press=self.ssh_help))
return screen(widgets, btns)
def rich_mode(self, sender):
self.controller.done(True)
def basic_mode(self, sender):
self.controller.done(False)
def ssh_help(self, sender):
menu = self.controller.app.help_menu
menu.ssh_info = self.ssh_info
menu.ssh_help()

View File

@ -14,7 +14,7 @@ class WelcomeViewTests(unittest.TestCase):
controller = mock.create_autospec(spec=WelcomeController) controller = mock.create_autospec(spec=WelcomeController)
with mock.patch("subiquity.ui.views.welcome.get_languages") as p: with mock.patch("subiquity.ui.views.welcome.get_languages") as p:
p.return_value = languages p.return_value = languages
return WelcomeView(controller, languages[0][0], False, None) return WelcomeView(controller, languages[0][0], False)
def test_basic(self): def test_basic(self):
# Clicking the button for a language calls "switch_language" # Clicking the button for a language calls "switch_language"

View File

@ -38,23 +38,6 @@ Select the language to use for the installer and to be configured in the
installed system. installed system.
""") """)
SERIAL_TEXT = """
As the installer is running on a serial console, it has started in
basic mode, using only the ASCII character set and black and white
colours.
If you are connecting from a terminal emulator such as gnome-terminal
that supports unicode and rich colours you can switch to "rich mode"
which uses unicode, colours and supports many languages.
"""
SSH_TEXT = """
You can also connect to the installer over the network via SSH, which
will allow use of rich mode.
"""
CLOUD_INIT_FAIL_TEXT = """ CLOUD_INIT_FAIL_TEXT = """
cloud-init failed to complete after 10 minutes of waiting. This cloud-init failed to complete after 10 minutes of waiting. This
suggests a bug, which we would appreciate help understanding. If you suggests a bug, which we would appreciate help understanding. If you
@ -81,15 +64,11 @@ def get_languages():
class WelcomeView(BaseView): class WelcomeView(BaseView):
title = "Willkommen! Bienvenue! Welcome! Добро пожаловать! Welkom!" title = "Willkommen! Bienvenue! Welcome! Добро пожаловать! Welkom!"
def __init__(self, controller, cur_lang, serial, ssh_info): def __init__(self, controller, cur_lang, serial):
self.controller = controller self.controller = controller
self.cur_lang = cur_lang self.cur_lang = cur_lang
if serial and not controller.app.rich_mode: self.serial = serial
s = self.make_serial_choices(ssh_info) super().__init__(self.make_language_choices())
self.title = "Welcome!"
else:
s = self.make_language_choices()
super().__init__(s)
def make_language_choices(self): def make_language_choices(self):
btns = [] btns = []
@ -109,51 +88,16 @@ class WelcomeView(BaseView):
user_arg=code)) user_arg=code))
lb = ListBox(btns) lb = ListBox(btns)
back = None
if self.serial:
back = other_btn(_("Back"), on_press=self.controller.cancel)
if current_index is not None: if current_index is not None:
lb.base_widget.focus_position = current_index lb.base_widget.focus_position = current_index
return screen( return screen(
lb, buttons=None, narrow_rows=True, lb, focus_buttons=False, narrow_rows=True,
buttons=[back] if back else None,
excerpt=_("Use UP, DOWN and ENTER keys to select your language.")) excerpt=_("Use UP, DOWN and ENTER keys to select your language."))
def make_serial_choices(self, ssh_info):
btns = [
other_btn(
label="Switch to rich mode",
on_press=self.enable_rich),
forward_btn(
label="Continue in basic mode",
on_press=self.choose_language,
user_arg='C'),
]
widgets = [
Text(""),
Text(rewrap(SERIAL_TEXT)),
Text(""),
]
if ssh_info:
widgets.append(Text(rewrap(SSH_TEXT)))
widgets.append(Text(""))
btns.insert(1, other_btn(
label="View SSH instructions",
on_press=self.ssh_help,
user_arg=ssh_info))
widgets.extend([
button_pile(btns),
])
lb = ListBox(widgets)
return screen(lb, buttons=None)
def enable_rich(self, sender):
self.controller.app.toggle_rich()
self.title = self.__class__.title
self.controller.ui.set_header(self.title)
self._w = self.make_language_choices()
def ssh_help(self, sender, ssh_info):
menu = self.controller.app.help_menu
menu.ssh_info = ssh_info
menu.ssh_help()
def choose_language(self, sender, code): def choose_language(self, sender, code):
log.debug('WelcomeView %s', code) log.debug('WelcomeView %s', code)
self.controller.done(code) self.controller.done(code)

View File

@ -312,6 +312,11 @@ class TuiApplication(Application):
self.aio_loop.call_later(0.06, _run_script) self.aio_loop.call_later(0.06, _run_script)
def set_rich(self, rich):
if rich == self.rich_mode:
return
self.toggle_rich()
def toggle_rich(self): def toggle_rich(self):
if self.rich_mode: if self.rich_mode:
urwid.util.set_encoding('ascii') urwid.util.set_encoding('ascii')