diff --git a/subiquity/client/client.py b/subiquity/client/client.py
index ed981b18..07df3c4f 100644
--- a/subiquity/client/client.py
+++ b/subiquity/client/client.py
@@ -93,6 +93,7 @@ class SubiquityClient(TuiApplication):
return SubiquityUI(self, self.help_menu)
controllers = [
+ "Serial",
"Welcome",
"Refresh",
"Keyboard",
diff --git a/subiquity/client/controllers/__init__.py b/subiquity/client/controllers/__init__.py
index fca8d162..66f0be3c 100644
--- a/subiquity/client/controllers/__init__.py
+++ b/subiquity/client/controllers/__init__.py
@@ -22,11 +22,13 @@ from .network import NetworkController
from .progress import ProgressController
from .proxy import ProxyController
from .refresh import RefreshController
+from .serial import SerialController
from .snaplist import SnapListController
from .ssh import SSHController
from .welcome import WelcomeController
from .zdev import ZdevController
+# see SubiquityClient.controllers for another list
__all__ = [
'FilesystemController',
'IdentityController',
@@ -37,6 +39,7 @@ __all__ = [
'ProxyController',
'RefreshController',
'RepeatedController',
+ 'SerialController',
'SnapListController',
'SSHController',
'WelcomeController',
diff --git a/subiquity/client/controllers/serial.py b/subiquity/client/controllers/serial.py
new file mode 100644
index 00000000..571e6039
--- /dev/null
+++ b/subiquity/client/controllers/serial.py
@@ -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 .
+
+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
diff --git a/subiquity/client/controllers/welcome.py b/subiquity/client/controllers/welcome.py
index 7b4ec645..ff600174 100644
--- a/subiquity/client/controllers/welcome.py
+++ b/subiquity/client/controllers/welcome.py
@@ -16,6 +16,7 @@
import logging
from subiquitycore import i18n
+from subiquitycore.tuicontroller import Skip
from subiquity.client.controller import SubiquityTuiController
from subiquity.ui.views.welcome import WelcomeView
@@ -27,14 +28,12 @@ class WelcomeController(SubiquityTuiController):
endpoint_name = 'locale'
async def make_ui(self):
+ if not self.app.rich_mode:
+ raise Skip()
language = await self.endpoint.GET()
i18n.switch_language(language)
- serial = self.app.opts.run_on_serial
- if serial:
- ssh_info = await self.app.client.meta.ssh_info.GET()
- else:
- ssh_info = None
- return WelcomeView(self, language, serial, ssh_info)
+ self.serial = self.app.opts.run_on_serial
+ return WelcomeView(self, language, self.serial)
def run_answers(self):
if 'lang' in self.answers:
@@ -45,6 +44,8 @@ class WelcomeController(SubiquityTuiController):
i18n.switch_language(code)
self.app.next_screen(self.endpoint.POST(code))
- def cancel(self):
- # Can't go back from here!
- pass
+ def cancel(self, sender=None):
+ if not self.serial:
+ # Can't go back from here unless we're on serial!
+ pass
+ self.app.prev_screen()
diff --git a/subiquity/server/controllers/locale.py b/subiquity/server/controllers/locale.py
index 8f019e75..c994dc16 100644
--- a/subiquity/server/controllers/locale.py
+++ b/subiquity/server/controllers/locale.py
@@ -31,9 +31,6 @@ class LocaleController(SubiquityController):
autoinstall_schema = {'type': 'string'}
autoinstall_default = 'en_US.UTF-8'
- def interactive(self):
- return self.app.interactive
-
def load_autoinstall_data(self, data):
os.environ["LANG"] = data
diff --git a/subiquity/ui/views/serial.py b/subiquity/ui/views/serial.py
new file mode 100644
index 00000000..3ae73a6d
--- /dev/null
+++ b/subiquity/ui/views/serial.py
@@ -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 .
+
+"""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()
diff --git a/subiquity/ui/views/tests/test_welcome.py b/subiquity/ui/views/tests/test_welcome.py
index 0bb83f03..091b81ff 100644
--- a/subiquity/ui/views/tests/test_welcome.py
+++ b/subiquity/ui/views/tests/test_welcome.py
@@ -14,7 +14,7 @@ class WelcomeViewTests(unittest.TestCase):
controller = mock.create_autospec(spec=WelcomeController)
with mock.patch("subiquity.ui.views.welcome.get_languages") as p:
p.return_value = languages
- return WelcomeView(controller, languages[0][0], False, None)
+ return WelcomeView(controller, languages[0][0], False)
def test_basic(self):
# Clicking the button for a language calls "switch_language"
diff --git a/subiquity/ui/views/welcome.py b/subiquity/ui/views/welcome.py
index 4b68dc56..8680c000 100644
--- a/subiquity/ui/views/welcome.py
+++ b/subiquity/ui/views/welcome.py
@@ -38,23 +38,6 @@ Select the language to use for the installer and to be configured in the
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 failed to complete after 10 minutes of waiting. This
suggests a bug, which we would appreciate help understanding. If you
@@ -81,15 +64,11 @@ def get_languages():
class WelcomeView(BaseView):
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.cur_lang = cur_lang
- if serial and not controller.app.rich_mode:
- s = self.make_serial_choices(ssh_info)
- self.title = "Welcome!"
- else:
- s = self.make_language_choices()
- super().__init__(s)
+ self.serial = serial
+ super().__init__(self.make_language_choices())
def make_language_choices(self):
btns = []
@@ -109,51 +88,16 @@ class WelcomeView(BaseView):
user_arg=code))
lb = ListBox(btns)
+ back = None
+ if self.serial:
+ back = other_btn(_("Back"), on_press=self.controller.cancel)
if current_index is not None:
lb.base_widget.focus_position = current_index
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."))
- 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):
log.debug('WelcomeView %s', code)
self.controller.done(code)
diff --git a/subiquitycore/tui.py b/subiquitycore/tui.py
index 2136d7d0..d21627ce 100644
--- a/subiquitycore/tui.py
+++ b/subiquitycore/tui.py
@@ -312,6 +312,11 @@ class TuiApplication(Application):
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):
if self.rich_mode:
urwid.util.set_encoding('ascii')