2020-03-24 10:16:25 +00:00
|
|
|
# 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/>.
|
|
|
|
|
|
|
|
""" Chooser
|
|
|
|
|
|
|
|
Chooser provides a view with recovery chooser actions.
|
|
|
|
|
|
|
|
"""
|
|
|
|
import logging
|
|
|
|
|
|
|
|
from urwid import (
|
|
|
|
connect_signal,
|
|
|
|
Text,
|
|
|
|
)
|
|
|
|
from subiquitycore.ui.buttons import (
|
|
|
|
danger_btn,
|
2020-04-01 14:01:16 +00:00
|
|
|
forward_btn,
|
2020-04-07 15:38:45 +00:00
|
|
|
back_btn,
|
2020-03-24 10:16:25 +00:00
|
|
|
)
|
|
|
|
from subiquitycore.ui.actionmenu import (
|
|
|
|
Action,
|
|
|
|
ActionMenu,
|
|
|
|
)
|
2020-04-01 14:01:16 +00:00
|
|
|
from subiquitycore.ui.container import Pile, ListBox
|
2020-03-24 10:16:25 +00:00
|
|
|
from subiquitycore.ui.utils import (
|
|
|
|
button_pile,
|
|
|
|
screen,
|
|
|
|
make_action_menu_row,
|
|
|
|
Color,
|
|
|
|
)
|
|
|
|
from subiquitycore.ui.table import TableRow, TablePile
|
|
|
|
from subiquitycore.view import BaseView
|
|
|
|
|
|
|
|
|
|
|
|
log = logging.getLogger("console_conf.views.chooser")
|
|
|
|
|
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
class ChooserBaseView(BaseView):
|
2020-04-01 14:01:16 +00:00
|
|
|
title = "Ubuntu Core"
|
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
def __init__(self, current, scr):
|
|
|
|
if current is not None:
|
|
|
|
self.title = current.model.display_name
|
|
|
|
|
|
|
|
super().__init__(scr)
|
|
|
|
|
|
|
|
|
|
|
|
def by_preferred_action_type(action):
|
|
|
|
"""Order action entries by having the 'run' mode first, then 'recover', then
|
|
|
|
'install', the rest is ordered alphabetically."""
|
|
|
|
return (action.mode != "run",
|
|
|
|
action.mode != "recover",
|
|
|
|
action.mode != "install",
|
|
|
|
action.title.lower())
|
|
|
|
|
2020-04-01 14:01:16 +00:00
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
class ChooserCurrentSystemView(ChooserBaseView):
|
|
|
|
excerpt = "Select action:"
|
|
|
|
|
|
|
|
def __init__(self, controller, current, has_more=False):
|
2020-04-01 14:01:16 +00:00
|
|
|
self.controller = controller
|
|
|
|
log.debug('more systems available: %s', has_more)
|
2020-04-07 15:38:45 +00:00
|
|
|
log.debug('current system: %s', current)
|
2020-04-01 14:01:16 +00:00
|
|
|
|
|
|
|
actions = []
|
2020-04-07 15:38:45 +00:00
|
|
|
for action in sorted(current.actions, key=by_preferred_action_type):
|
|
|
|
actions.append(forward_btn(label=action.title.capitalize(),
|
2020-04-01 14:01:16 +00:00
|
|
|
on_press=self._current_system_action,
|
|
|
|
user_arg=(current, action)))
|
|
|
|
|
|
|
|
if has_more:
|
|
|
|
# add a button to show the other systems
|
|
|
|
actions.append(Text(""))
|
|
|
|
actions.append(forward_btn(label="Show all available systems",
|
|
|
|
on_press=self._more_options))
|
|
|
|
|
|
|
|
lb = ListBox(actions)
|
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
super().__init__(current,
|
|
|
|
screen(
|
|
|
|
lb,
|
|
|
|
narrow_rows=True,
|
|
|
|
excerpt=self.excerpt))
|
2020-04-01 14:01:16 +00:00
|
|
|
|
|
|
|
def _current_system_action(self, sender, arg):
|
|
|
|
current, action = arg
|
|
|
|
self.controller.select(current, action)
|
|
|
|
|
|
|
|
def _more_options(self, sender):
|
|
|
|
self.controller.more_options()
|
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
def back(self, result):
|
|
|
|
self.controller.back()
|
2020-04-01 14:01:16 +00:00
|
|
|
|
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
class ChooserView(ChooserBaseView):
|
2020-03-24 10:16:25 +00:00
|
|
|
excerpt = ("Select one of available recovery systems and a desired "
|
|
|
|
"action to execute.")
|
|
|
|
|
|
|
|
def __init__(self, controller, systems):
|
|
|
|
self.controller = controller
|
|
|
|
|
|
|
|
heading_table = TablePile([
|
|
|
|
TableRow([
|
|
|
|
Color.info_minor(Text(header)) for header in [
|
2020-04-01 14:00:34 +00:00
|
|
|
"LABEL", "MODEL", "PUBLISHER", ""
|
2020-03-24 10:16:25 +00:00
|
|
|
]
|
|
|
|
])
|
|
|
|
],
|
|
|
|
spacing=2)
|
|
|
|
|
|
|
|
trows = []
|
2020-04-01 14:00:34 +00:00
|
|
|
systems = sorted(systems,
|
|
|
|
key=lambda s: (s.brand.display_name,
|
|
|
|
s.model.display_name,
|
|
|
|
s.current,
|
|
|
|
s.label))
|
2020-03-24 10:16:25 +00:00
|
|
|
for s in systems:
|
|
|
|
actions = []
|
|
|
|
log.debug('actions: %s', s.actions)
|
2020-04-07 15:38:45 +00:00
|
|
|
for act in sorted(s.actions, key=by_preferred_action_type):
|
|
|
|
actions.append(Action(label=act.title.capitalize(),
|
2020-03-24 10:16:25 +00:00
|
|
|
value=act,
|
|
|
|
enabled=True))
|
|
|
|
menu = ActionMenu(actions)
|
|
|
|
connect_signal(menu, 'action', self._system_action, s)
|
|
|
|
srow = make_action_menu_row([
|
|
|
|
Text(s.label),
|
|
|
|
Text(s.model.display_name),
|
|
|
|
Text(s.brand.display_name),
|
2020-04-07 15:38:45 +00:00
|
|
|
Text("(installed)" if s.current else ""),
|
2020-03-24 10:16:25 +00:00
|
|
|
menu,
|
|
|
|
], menu)
|
|
|
|
trows.append(srow)
|
|
|
|
|
|
|
|
systems_table = TablePile(trows, spacing=2)
|
|
|
|
systems_table.bind(heading_table)
|
|
|
|
rows = [
|
|
|
|
Pile([heading_table, systems_table]),
|
|
|
|
]
|
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
buttons = []
|
|
|
|
if controller.model.current is not None:
|
|
|
|
# back to options of current system
|
|
|
|
buttons.append(back_btn("BACK", on_press=self.back))
|
2020-03-24 10:16:25 +00:00
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
super().__init__(controller.model.current,
|
|
|
|
screen(
|
|
|
|
rows=rows,
|
|
|
|
buttons=button_pile(buttons),
|
|
|
|
focus_buttons=False,
|
|
|
|
excerpt=self.excerpt))
|
2020-03-24 10:16:25 +00:00
|
|
|
|
|
|
|
def _system_action(self, sender, action, system):
|
|
|
|
self.controller.select(system, action)
|
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
def back(self, result):
|
|
|
|
self.controller.back()
|
2020-03-24 10:16:25 +00:00
|
|
|
|
|
|
|
|
2020-04-07 15:38:45 +00:00
|
|
|
class ChooserConfirmView(ChooserBaseView):
|
|
|
|
|
|
|
|
canned_summary = {
|
|
|
|
"run": "Continue running the system without any changes.",
|
|
|
|
"recover": ("You have requested to reboot the system into recovery "
|
|
|
|
"mode."),
|
2020-04-08 09:57:00 +00:00
|
|
|
"install": ("You are about to {action_lower} the system version "
|
|
|
|
"{version} for {model} from {publisher}.\n\n"
|
2020-04-07 15:38:45 +00:00
|
|
|
"This will remove all existing user data on the "
|
|
|
|
"device.\n\n"
|
|
|
|
"The system will reboot in the process."),
|
|
|
|
}
|
|
|
|
default_summary = ("You are about to execute action \"{action}\" using "
|
|
|
|
"system version {version} for device {model} from "
|
|
|
|
"{publisher}.\n\n"
|
|
|
|
"Make sure you understand the consequences of doing "
|
|
|
|
"so.")
|
2020-03-24 10:16:25 +00:00
|
|
|
|
|
|
|
def __init__(self, controller, selection):
|
|
|
|
self.controller = controller
|
|
|
|
|
|
|
|
buttons = [
|
|
|
|
danger_btn("CONFIRM", on_press=self.confirm),
|
2020-04-07 15:38:45 +00:00
|
|
|
back_btn("BACK", on_press=self.back),
|
2020-03-24 10:16:25 +00:00
|
|
|
]
|
2020-04-07 15:38:45 +00:00
|
|
|
fmt = self.canned_summary.get(selection.action.mode,
|
|
|
|
self.default_summary)
|
|
|
|
summary = fmt.format(action=selection.action.title,
|
2020-04-08 09:57:00 +00:00
|
|
|
action_lower=selection.action.title.lower(),
|
2020-04-07 15:38:45 +00:00
|
|
|
model=selection.system.model.display_name,
|
|
|
|
publisher=selection.system.brand.display_name,
|
|
|
|
version=selection.system.label)
|
2020-03-24 10:16:25 +00:00
|
|
|
rows = [
|
2020-04-07 15:38:45 +00:00
|
|
|
Text(summary),
|
2020-03-24 10:16:25 +00:00
|
|
|
]
|
2020-04-07 15:38:45 +00:00
|
|
|
super().__init__(controller.model.current,
|
|
|
|
screen(
|
|
|
|
rows=rows,
|
|
|
|
buttons=button_pile(buttons),
|
|
|
|
focus_buttons=False))
|
2020-03-24 10:16:25 +00:00
|
|
|
|
|
|
|
def confirm(self, result):
|
|
|
|
self.controller.confirm()
|
2020-04-07 15:38:45 +00:00
|
|
|
|
|
|
|
def back(self, result):
|
|
|
|
self.controller.back()
|