From f4f5d58026bb92e5bdb06d7605fc34dd4805164a Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Fri, 11 May 2018 16:30:41 +1200 Subject: [PATCH] first cut at snaplist view --- subiquity/controllers/__init__.py | 1 + subiquity/controllers/snaplist.py | 13 ++++++-- subiquity/core.py | 1 + subiquity/models/snaplist.py | 22 ++++++++++--- subiquity/models/subiquity.py | 2 ++ subiquity/ui/views/snaplist.py | 54 +++++++++++++++++++++++++++++++ 6 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 subiquity/ui/views/snaplist.py diff --git a/subiquity/controllers/__init__.py b/subiquity/controllers/__init__.py index ff67cbd5..774dac42 100644 --- a/subiquity/controllers/__init__.py +++ b/subiquity/controllers/__init__.py @@ -22,4 +22,5 @@ from .installprogress import InstallProgressController # NOQA from .filesystem import FilesystemController # NOQA from .keyboard import KeyboardController # NOQA from .proxy import ProxyController # NOQA +from .snaplist import SnapListController from .welcome import WelcomeController # NOQA diff --git a/subiquity/controllers/snaplist.py b/subiquity/controllers/snaplist.py index 1b71f865..0e9b4315 100644 --- a/subiquity/controllers/snaplist.py +++ b/subiquity/controllers/snaplist.py @@ -17,7 +17,7 @@ import logging from subiquitycore.controller import BaseController -from subiquity.ui.views import SnapListView +from subiquity.ui.views.snaplist import SnapListView log = logging.getLogger('subiquity.controllers.snaplist') @@ -26,8 +26,17 @@ class SnapListController(BaseController): def __init__(self, common): super().__init__(common) - self.model = self.all_model.SnapList + self.model = self.base_model.snaplist def default(self): + self.ui.set_header( + _("Featured Server Snaps"), + _("These are popular snaps in server environments. Select or deselect with SPACE, press ENTER to see more details of the package, publisher and versions available."), + ) self.ui.set_body(SnapListView(self.model, self)) + def done(self, snaps_to_install): + self.signal.emit_signal("next-screen") + + def cancel(self, sender=None): + self.signal.emit_signal("prev-screen") diff --git a/subiquity/core.py b/subiquity/core.py index 9a1a20af..5af6d25c 100644 --- a/subiquity/core.py +++ b/subiquity/core.py @@ -38,6 +38,7 @@ class Subiquity(Application): "Proxy", "Filesystem", "Identity", + "SnapList", "InstallProgress", ] diff --git a/subiquity/models/snaplist.py b/subiquity/models/snaplist.py index 8dee2ec0..9327e8e3 100644 --- a/subiquity/models/snaplist.py +++ b/subiquity/models/snaplist.py @@ -13,6 +13,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import json +import os + import attr @attr.s(cmp=False) @@ -40,10 +43,21 @@ class SnapListModel: pass def get_snap_list(self): - return [ - Snap("etcd", "Resilient key-value store by CoreOS", "tvansteenburgh", "Etcd is a high availability key-value store, implementing the RAFT algorithm to deal with failover within the etcd cluster. Popular in the Docker community as a shared store of small but important data in a distributed application."), - ] - + opd = os.path.dirname + opj = os.path.join + snap_data_dir = opj(opd(opd(opd(__file__))), 'examples', 'snaps') + snap_find_output = opj(snap_data_dir, 'find-output.json') + with open(snap_find_output) as fp: + data = json.load(fp) + r = [] + for s in data['result']: + kw = {} + kw['name'] = s['name'] + kw['summary'] = s['summary'] + kw['publisher'] = s['developer'] + kw['description'] = s['description'] + r.append(SnapInfo(**kw)) + return r def set_installed_list(self, to_install): self.to_install = to_install diff --git a/subiquity/models/subiquity.py b/subiquity/models/subiquity.py index 0f3a58e7..949c271f 100644 --- a/subiquity/models/subiquity.py +++ b/subiquity/models/subiquity.py @@ -26,6 +26,7 @@ from .installpath import InstallpathModel from .keyboard import KeyboardModel from .locale import LocaleModel from .proxy import ProxyModel +from .snaplist import SnapListModel def setup_yaml(): @@ -50,6 +51,7 @@ class SubiquityModel: self.filesystem = FilesystemModel(common['prober']) self.identity = IdentityModel() self.proxy = ProxyModel() + self.snaplist = SnapListModel(common) def _cloud_init_config(self): user = self.identity.user diff --git a/subiquity/ui/views/snaplist.py b/subiquity/ui/views/snaplist.py new file mode 100644 index 00000000..2c1566b7 --- /dev/null +++ b/subiquity/ui/views/snaplist.py @@ -0,0 +1,54 @@ +# 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 . + +import logging + +from urwid import ( + CheckBox, + Text, + ) + +from subiquitycore.ui.buttons import ok_btn, cancel_btn +from subiquitycore.ui.container import Columns +from subiquitycore.ui.utils import button_pile, Color, screen +from subiquitycore.view import BaseView + + +log = logging.getLogger("subiquity.views.welcome") + + +class SnapListView(BaseView): + + def __init__(self, model, controller): + self.model = model + self.controller = controller + self.to_install = [] + body = [] + snaps = self.model.get_snap_list() + name_len = max([len(snap.name) for snap in snaps]) + for snap in snaps: + body.append(Color.menu_button(Columns([ + (name_len+4, CheckBox(snap.name)), + Text(snap.summary, wrap='clip'), + ], dividechars=1))) + ok = ok_btn(label=_("OK"), on_press=self.done) + cancel = cancel_btn(label=_("Cancel"), on_press=self.done) + super().__init__(screen(body, button_pile([ok, cancel]))) + + def done(self, sender=None): + self.controller.done(self.to_install) + + def cancel(self, sender=None): + self.controller.cancel()