diff --git a/subiquity/controllers/__init__.py b/subiquity/controllers/__init__.py index 3b0cad26..fa7e1d85 100644 --- a/subiquity/controllers/__init__.py +++ b/subiquity/controllers/__init__.py @@ -18,3 +18,4 @@ from .installpath import InstallpathController from .network import NetworkController from .filesystem import FilesystemController from .installprogress import InstallProgressController +from .identity import IdentityController diff --git a/subiquity/controllers/filesystem.py b/subiquity/controllers/filesystem.py index fbcf9bac..b510b4e4 100644 --- a/subiquity/controllers/filesystem.py +++ b/subiquity/controllers/filesystem.py @@ -56,6 +56,7 @@ class FilesystemController(ControllerPolicy): curtin_write_storage_actions(actions=actions) log.info("Generating post-install config") curtin_write_postinst_config() + urwid.emit_signal(self.signal, 'identity:show') # self.install_progress() # Filesystem/Disk partition ----------------------------------------------- diff --git a/subiquity/controllers/identity.py b/subiquity/controllers/identity.py new file mode 100644 index 00000000..54842439 --- /dev/null +++ b/subiquity/controllers/identity.py @@ -0,0 +1,33 @@ +# Copyright 2015 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 . + +from subiquity.controller import ControllerPolicy +from subiquity.models import IdentityModel +from subiquity.ui.views import IdentityView + + +class IdentityController(ControllerPolicy): + def __init__(self, ui, signal): + self.ui = ui + self.signal = signal + self.model = IdentityModel() + + def identity(self): + title = "Profile setup" + excerpt = ("Input your username and password to log in to the system.") + footer = "" + self.ui.set_header(title, excerpt) + self.ui.set_footer(footer) + self.ui.set_body(IdentityView(self.model, self.signal)) diff --git a/subiquity/core.py b/subiquity/core.py index 35645dcc..5b96a901 100644 --- a/subiquity/core.py +++ b/subiquity/core.py @@ -24,6 +24,7 @@ from subiquity.controllers import (WelcomeController, InstallpathController, NetworkController, FilesystemController, + IdentityController, InstallProgressController) log = logging.getLogger('subiquity.core') @@ -44,6 +45,7 @@ class Controller: "installpath": InstallpathController(self.ui, self.signal), "network": NetworkController(self.ui, self.signal), "filesystem": FilesystemController(self.ui, self.signal), + "identity": IdentityController(self.ui, self.signal), "progress": InstallProgressController(self.ui, self.signal), } self._connect_base_signals() diff --git a/subiquity/models/__init__.py b/subiquity/models/__init__.py index 5a9f1262..15dff962 100644 --- a/subiquity/models/__init__.py +++ b/subiquity/models/__init__.py @@ -17,3 +17,4 @@ from .filesystem import FilesystemModel from .installpath import InstallpathModel from .network import NetworkModel from .welcome import WelcomeModel +from .identity import IdentityModel diff --git a/subiquity/models/identity.py b/subiquity/models/identity.py index 471780ff..2d3ac415 100644 --- a/subiquity/models/identity.py +++ b/subiquity/models/identity.py @@ -44,11 +44,6 @@ class IdentityModel(ModelPolicy): "validate_confirm_password") ] - username = None - password = None - confirm_password = None - encrypted_password = None - def get_signals(self): return self.signals diff --git a/subiquity/ui/interactive.py b/subiquity/ui/interactive.py index cb4af229..a4434d60 100644 --- a/subiquity/ui/interactive.py +++ b/subiquity/ui/interactive.py @@ -37,6 +37,13 @@ class StringEditor(WidgetWrap): return self._edit.get_edit_text() +class PasswordEditor(StringEditor): + """ Password input prompt with masking + """ + def __init__(self, caption, mask="*"): + super().__init__(caption, mask=mask) + + class IntegerEditor(WidgetWrap): """ IntEdit input class """ diff --git a/subiquity/ui/views/__init__.py b/subiquity/ui/views/__init__.py index fcb66f7c..b32df8f7 100644 --- a/subiquity/ui/views/__init__.py +++ b/subiquity/ui/views/__init__.py @@ -18,3 +18,4 @@ from .network import NetworkView from .installpath import InstallpathView from .installprogress import ProgressOutput, ProgressView from .welcome import WelcomeView +from .identity import IdentityView diff --git a/subiquity/ui/views/identity.py b/subiquity/ui/views/identity.py new file mode 100644 index 00000000..52de0c12 --- /dev/null +++ b/subiquity/ui/views/identity.py @@ -0,0 +1,79 @@ +# Copyright 2015 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 (Pile, emit_signal) +from subiquity.ui.widgets import Box +from subiquity.ui.buttons import done_btn, cancel_btn +from subiquity.ui.interactive import StringEditor, PasswordEditor +from subiquity.ui.utils import Padding, Color +from subiquity.view import ViewPolicy + +log = logging.getLogger("subiquity.views.identity") + + +class IdentityView(ViewPolicy): + def __init__(self, model, signal): + self.model = model + self.signal = signal + self.items = [] + self.username = StringEditor(caption="Username: ") + self.password = PasswordEditor(caption="Password: ") + self.confirm_password = PasswordEditor(caption="Confirm Password: ") + + body = [ + Padding.center_79(self._build_model_inputs()), + Padding.line_break(""), + Padding.center_20(self._build_buttons()), + ] + super().__init__(Box(body)) + + def _build_buttons(self): + cancel = cancel_btn(on_press=self.cancel) + done = done_btn(on_press=self.done) + + buttons = [ + Color.button_secondary(cancel, focus_map='button_secondary focus'), + Color.button_secondary(done, focus_map='button_secondary focus') + ] + return Pile(buttons) + + def _build_model_inputs(self): + sl = [ + self.username, + self.password, + self.confirm_password + ] + return Pile(sl) + + def done(self, result): + log.debug("User input: {} {} {}".format(self.username.value, + self.password.value, + self.confirm_password.value)) + result = { + "username": self.username.value, + "password": self.password.value, + "confirm_password": self.confirm_password.value + } + log.debug("User input: {}".format(result)) + # emit_signal(self.signal, 'installpath:show') + + def cancel(self, button): + self.signal.emit_signal("quit")