add controller policy

Signed-off-by: Adam Stokes <adam.stokes@ubuntu.com>
This commit is contained in:
Adam Stokes 2015-06-24 14:28:47 -04:00
parent 771d9503d5
commit 66ff8fef18
6 changed files with 115 additions and 145 deletions

View File

@ -17,12 +17,11 @@
import argparse
import sys
import logging
import urwid
import urwid.curses_display
from subiquity.palette import STYLES, STYLES_MONO
from subiquity.app import Application
from subiquity.log import setup_logger
from subiquity import __version__ as VERSION
from subiquity.controllers import BaseController as Subiquity
from subiquity.ui.frame import SubiquityUI
from subiquity.palette import STYLES, STYLES_MONO
def parse_options(argv):
@ -41,17 +40,14 @@ def main():
logger = logging.getLogger('subiquity')
logger.info("Starting SUbiquity v{}".format(VERSION))
logger.info("Arguments passed: {}".format(sys.argv))
if opts.run_on_serial:
# screen = urwid.curses_display.Screen()
screen = urwid.raw_display.Screen()
screen.register_palette(STYLES_MONO)
else:
screen = urwid.raw_display.Screen()
screen.set_mouse_tracking(False)
screen.set_terminal_properties(256)
screen.register_palette(STYLES)
Application(screen, opts).start()
ui = SubiquityUI()
palette = STYLES
if opts.run_on_serial:
palette = STYLES_MONO
subiquity_interface = Subiquity(ui, palette, opts)
subiquity_interface.run()
if __name__ == '__main__':
main()

View File

@ -1,64 +0,0 @@
# 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 <http://www.gnu.org/licenses/>.
""" Application entry point """
import urwid
import logging
from subiquity.routes import Routes
from subiquity.ui.frame import SubiquityUI
log = logging.getLogger('subiquity.app')
class ApplicationError(Exception):
""" Exception in Application Class """
pass
class Application:
def __init__(self, screen, opts):
self.screen = screen
self.opts = opts
self.routes = Routes
self.ui = SubiquityUI()
self.loop = None
def unhandled_input(self, key):
if key in ('Q', 'q', 'esc'):
raise urwid.ExitMainLoop()
if key in ('r', 'R'):
self.loop.draw_screen()
def start(self):
try:
self.loop = urwid.MainLoop(self.ui,
screen=self.screen,
unhandled_input=self.unhandled_input)
self.loop.run()
except:
raise ApplicationError("Exception in loop.run()")
return self.initialize()
def initialize(self):
# Build common dictionary for use throughout application
common = dict(opts=self.opts,
routes=self.routes,
ui=self.ui,
loop=self.loop)
# Setup first controller
controller = Routes.first()
return controller(common).show()

View File

@ -14,7 +14,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
from abc import ABCMeta, abstractmethod
import urwid
from subiquity.routes import Routes
log = logging.getLogger('subiquity.controller')
@ -25,59 +26,57 @@ class BaseControllerError(Exception):
pass
class BaseController(metaclass=ABCMeta):
controller_name = None
class BaseController:
def __init__(self, ui, palette, opts):
self.ui = ui
self.palette = palette
self.opts = opts
def __init__(self, common):
self.common = common
def next_controller(self, *args, **kwds):
controller = Routes.next()
controller(self).show(*args, **kwds)
@classmethod
def name(cls):
if cls.controller_name:
return cls.controller_name
return cls.__name__.lower()
@abstractmethod
def show(self, *args, **kwds):
""" 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
def set_header(self, title, excerpt):
self.common['ui'].set_header(title, excerpt)
self.redraw_screen()
def set_footer(self, message):
self.common['ui'].set_footer(message)
self.redraw_screen()
def set_body(self, widget):
self.common['ui'].set_body(widget)
self.redraw_screen()
def prev_controller(self, *args, **kwds):
controller = Routes.prev()
controller(self).show(*args, **kwds)
def redraw_screen(self):
try:
self.common['loop'].draw_screen()
self.loop.draw_screen()
except AssertionError as e:
raise BaseControllerError(e)
log.exception("exception failure in redraw_screen")
raise e
def next_controller(self, *args, **kwds):
controller = self.common['routes'].next()
controller(self.common).show(*args, **kwds)
def set_alarm_in(self, interval, cb):
self.loop.set_alarm_in(interval, cb)
return
def header_hotkeys(self, key):
if key in ['q', 'Q']:
raise urwid.ExitMainLoop()
def set_body(self, w):
self.ui.set_body(w)
self.redraw_screen()
def prev_controller(self, *args, **kwds):
controller = self.common['routes'].prev()
controller(self.common).show(*args, **kwds)
def set_header(self, title, excerpt):
self.ui.set_header(title, excerpt)
self.redraw_screen()
def set_footer(self, message):
self.ui.set_footer(message)
self.redraw_screen()
def run(self):
""" Run eventloop
"""
self.loop = urwid.MainLoop(self.ui, self.palette,
unhandled_input=self.header_hotkeys)
try:
self.loop.run()
initial_controller = Routes.first()
self.set_body(initial_controller(self).show())
except:
log.exception("Exception in controller.run():")
raise

View File

@ -13,7 +13,7 @@
# 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/>.
from subiquity.controllers import BaseController, BaseControllerError
from subiquity.controllers.policy import ControllerPolicy
from subiquity.views.installpath import InstallpathView
from subiquity.models.installpath import InstallpathModel
import logging
@ -21,9 +21,9 @@ import logging
log = logging.getLogger('subiquity.installpath')
class InstallpathController(BaseController):
class InstallpathController(ControllerPolicy):
"""InstallpathController"""
controller_name = "Installation path controller"
title = "15.10"
excerpt = ("Welcome to Ubuntu! The worlds favourite platform "
"for clouds, clusters and amazing internet things. "
@ -34,17 +34,17 @@ class InstallpathController(BaseController):
def show(self, *args, **kwds):
log.debug("Loading install path controller")
self.set_header(self.title, self.excerpt)
self.set_footer(self.footer)
self.ui.set_header(self.title, self.excerpt)
self.ui.set_footer(self.footer)
model = InstallpathModel()
self.set_body(InstallpathView(model, self.finish))
self.ui.set_body(InstallpathView(model, self.finish))
return
def finish(self, install_selection=None):
if install_selection is None:
raise BaseControllerError("No install selection found")
raise Exception("No install selection found")
else:
raise BaseControllerError(
raise Exception(
"Install selection: {}".format(install_selection))
__controller_class__ = InstallpathController

View File

@ -0,0 +1,41 @@
# 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 <http://www.gnu.org/licenses/>.
""" Controller policy """
from abc import ABCMeta, abstractmethod
class ControllerPolicy(metaclass=ABCMeta):
def __init__(self, ui):
self.ui = ui
@abstractmethod
def show(self, *args, **kwds):
""" 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

View File

@ -13,7 +13,7 @@
# 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/>.
from subiquity.controllers import BaseController
from subiquity.controllers.policy import ControllerPolicy
from subiquity.views.welcome import WelcomeView
from subiquity.models.welcome import WelcomeModel
import subprocess
@ -23,20 +23,18 @@ import logging
log = logging.getLogger('subiquity.controllers.welcome')
class WelcomeController(BaseController):
class WelcomeController(ControllerPolicy):
"""WelcomeController"""
controller_name = "Language Selection Controller"
title = "Wilkommen! Bienvenue! Welcome! Zdrastvutie! Welkom!"
excerpt = "Please choose your preferred language"
footer = ("Use UP, DOWN arrow keys, and ENTER, to "
"select your language.")
def show(self, *args, **kwds):
title = "Wilkommen! Bienvenue! Welcome! Zdrastvutie! Welkom!"
excerpt = "Please choose your preferred language"
footer = ("Use UP, DOWN arrow keys, and ENTER, to "
"select your language.")
self.set_header(title, excerpt)
self.set_footer(footer)
self.ui.set_header(self.title, self.excerpt)
self.ui.set_footer(self.footer)
model = WelcomeModel()
self.set_body(WelcomeView(model, self.finish))
self.ui.set_body(WelcomeView(model, self.finish))
return
def finish(self, language=None):
@ -45,6 +43,6 @@ class WelcomeController(BaseController):
"more previous controllers to render.")
self.selected_language = language
# subprocess.check_call("/usr/local/bin/curtin_wrap.sh")
return self.next_controller()
return self.ui.next_controller()
__controller_class__ = WelcomeController