From ce18689b94d1e44b15562c7c10cd33c8785a1ad2 Mon Sep 17 00:00:00 2001 From: Adam Stokes Date: Wed, 10 Jun 2015 18:43:56 -0400 Subject: [PATCH] Split out controllers/views, add additional UI utilities Signed-off-by: Adam Stokes --- bin/subiquity | 4 +-- subiquity/controllers/__init__.py | 43 ++++++++++++++++++++++++ subiquity/controllers/welcome.py | 28 +++++++++++++++ subiquity/palette.py | 2 +- subiquity/ui/utils.py | 38 +++++++++++++++++++-- subiquity/views/__init__.py | 14 ++++++++ subiquity/{views.py => views/welcome.py} | 22 ++++++------ 7 files changed, 135 insertions(+), 16 deletions(-) create mode 100644 subiquity/controllers/__init__.py create mode 100644 subiquity/controllers/welcome.py create mode 100644 subiquity/views/__init__.py rename subiquity/{views.py => views/welcome.py} (77%) diff --git a/bin/subiquity b/bin/subiquity index f0ead173..a425a1cc 100755 --- a/bin/subiquity +++ b/bin/subiquity @@ -19,7 +19,7 @@ import sys import urwid import urwid.curses_display from subiquity.palette import STYLES -from subiquity.views import StartView +from subiquity.controllers.welcome import WelcomeController def parse_options(argv): @@ -45,7 +45,7 @@ def main(): def unhandled_input(key): if key in ('Q', 'q', 'esc'): raise urwid.ExitMainLoop() - urwid.MainLoop(StartView(), screen=screen, + urwid.MainLoop(WelcomeController().show(), screen=screen, unhandled_input=unhandled_input).run() if __name__ == '__main__': diff --git a/subiquity/controllers/__init__.py b/subiquity/controllers/__init__.py new file mode 100644 index 00000000..87f3306d --- /dev/null +++ b/subiquity/controllers/__init__.py @@ -0,0 +1,43 @@ +# 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 abc import ABCMeta, abstractmethod + + +class BaseController(metaclass=ABCMeta): + controller_name = None + + @classmethod + def name(cls): + if cls.controller_name: + return cls.controller_name + return cls.__name__.lower() + + @abstractmethod + def show(self): + """ Implements show action for the controller + + Renders the View for controller. + """ + pass + + @abstractmethod + def finish(self): + """ Implements finish action for controller. + + This handles any callback data/procedures required + to move to the next controller or end the install. + """ + pass diff --git a/subiquity/controllers/welcome.py b/subiquity/controllers/welcome.py new file mode 100644 index 00000000..b8f5cf0a --- /dev/null +++ b/subiquity/controllers/welcome.py @@ -0,0 +1,28 @@ +# 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.controllers import BaseController +from subiquity.views.welcome import WelcomeView + + +class WelcomeController(BaseController): + """WelcomeController""" + controller_name = "Welcome to Ubuntu" + + def show(self): + return WelcomeView(self.finish) + + def finish(self, code, val): + raise SystemExit("Saw res: {}, val: {}".format(code, val)) diff --git a/subiquity/palette.py b/subiquity/palette.py index 183b4851..c7b884fb 100644 --- a/subiquity/palette.py +++ b/subiquity/palette.py @@ -18,7 +18,7 @@ def apply_default_colors(cls): color_map = {'orange': '#d51', - 'light_orange': '#d81', + 'light_orange': '#d31', 'white': 'white', 'black': 'black', 'light_aubergine': '#77216F', diff --git a/subiquity/ui/utils.py b/subiquity/ui/utils.py index 5556033d..97066a24 100644 --- a/subiquity/ui/utils.py +++ b/subiquity/ui/utils.py @@ -19,6 +19,40 @@ from urwid import Padding as _Padding from functools import partialmethod +def apply_padders(cls): + """ Decorator for generating useful padding methods + + Loops through and generates methods like: + + Padding.push_1(Widget) + + Sets the left padding attribute by 1 + + Padding.pull_24(Widget) + + Sets right padding attribute by 24. + + Padding.center_50(Widget) + + Provides center padding with a relative width of 50 + """ + padding_count = 100 + + for i in range(1, padding_count): + setattr(cls, 'push_{}'.format(i), partialmethod(_Padding, left=i)) + setattr(cls, 'pull_{}'.format(i), partialmethod(_Padding, right=i)) + setattr(cls, 'center_{}'.format(i), + partialmethod(_Padding, align='center', + width=('relative', i))) + setattr(cls, 'left_{}'.format(i), + partialmethod(_Padding, align='left', + width=('relative', i))) + setattr(cls, 'right_{}'.format(i), + partialmethod(_Padding, align='right', + width=('relative', i))) + return cls + + +@apply_padders class Padding: - center = partialmethod(_Padding, align='center', - width=('relative', 50)) + pass diff --git a/subiquity/views/__init__.py b/subiquity/views/__init__.py new file mode 100644 index 00000000..8008b43a --- /dev/null +++ b/subiquity/views/__init__.py @@ -0,0 +1,14 @@ +# 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 . diff --git a/subiquity/views.py b/subiquity/views/welcome.py similarity index 77% rename from subiquity/views.py rename to subiquity/views/welcome.py index ab337df3..34aedbd2 100644 --- a/subiquity/views.py +++ b/subiquity/views/welcome.py @@ -13,25 +13,21 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from urwid import (WidgetWrap, ListBox, AttrWrap, Columns, Text, - # emitters - signals, emit_signal) +from urwid import (WidgetWrap, ListBox, AttrWrap, Columns, Text) from subiquity.ui.anchors import Header, Footer, Body # NOQA from subiquity.ui.buttons import confirm_btn, cancel_btn from subiquity.ui.utils import Padding -class StartView(WidgetWrap): - __metaclass__ = signals.MetaSignals - signals = ['done'] - - def __init__(self): +class WelcomeView(WidgetWrap): + def __init__(self, cb=None): Header.title = "SUbiquity - Ubiquity for Servers" + self.cb = cb self.layout = [ Header(), Text(""), Text("Begin the installation", align='center'), - Padding.center(self._build_buttons()), + Padding.center_50(self._build_buttons()), Footer() ] super().__init__(ListBox(self.layout)) @@ -46,7 +42,11 @@ class StartView(WidgetWrap): return Columns(self.buttons) def confirm(self, button): - emit_signal(self, 'done', True) + if self.cb is not None: + return self.cb(True, 'Moving to next controller.') def cancel(self, button): - emit_signal(self, 'done', False) + if self.cb is None: + raise SystemExit('Cancelled.') + else: + return self.cb(False, 'Cancelled with callback.')