move to a model where different types of fs device get different menus

This commit is contained in:
Michael Hudson-Doyle 2018-07-04 11:28:05 +12:00
parent 51f0a3561c
commit 3a2d7a8899
4 changed files with 86 additions and 54 deletions

View File

@ -280,7 +280,7 @@ class FilesystemController(BaseController):
bootable = self.model.bootable()
log.debug('model has bootable device? {}'.format(bootable))
can_be_boot = disk.supports_action(DeviceAction.MAKE_BOOT)
can_be_boot = DeviceAction.MAKE_BOOT in disk.supported_actions
if not bootable and len(disk.partitions()) == 0 and can_be_boot:
part = self._create_boot_partition(disk)

View File

@ -162,16 +162,17 @@ def asdict(inst):
class DeviceAction(enum.Enum):
INFO = enum.auto()
EDIT = enum.auto()
PARTITION = enum.auto()
FORMAT = enum.auto()
DELETE = enum.auto()
MAKE_BOOT = enum.auto()
INFO = _("Info")
EDIT = _("Edit")
PARTITION = _("Add Partition")
CREATE_LV = _("Create Logical Volume")
FORMAT = _("Format")
DELETE = _("Delete")
MAKE_BOOT = _("Make Boot Device")
@attr.s(cmp=False)
class _Formattable:
class _Formattable(ABC):
# Base class for anything that can be formatted and mounted,
# e.g. a disk or a RAID or a partition.
@ -189,8 +190,14 @@ class _Formattable:
def constructed_device(self):
return self._constructed_device
def supports_action(self, action):
return getattr(self, "_supports_" + action.name)
@property
@abstractmethod
def supported_actions(self):
pass
def action_possible(self, action):
assert action in self.supported_actions
return getattr(self, "_can_" + action.name)
# Nothing is put in the first and last megabytes of the disk to allow
@ -337,14 +344,18 @@ class Disk(_Device):
return self.serial
return self.path
_supports_INFO = True
_supports_EDIT = False
_supports_PARTITION = property(lambda self: self.free_for_partitions > 0)
_supports_FORMAT = property(
supported_actions = [
DeviceAction.INFO,
DeviceAction.PARTITION,
DeviceAction.FORMAT,
DeviceAction.MAKE_BOOT,
]
_can_INFO = True
_can_PARTITION = property(lambda self: self.free_for_partitions > 0)
_can_FORMAT = property(
lambda self: len(self._partitions) == 0 and
self._constructed_device is None)
_supports_DELETE = False
_supports_MAKE_BOOT = property(
_can_MAKE_BOOT = property(
lambda self:
not self.grub_device and self._fs is None
and self._constructed_device is None)
@ -385,15 +396,14 @@ class Partition(_Formattable):
def path(self):
return "%s%s" % (self.device.path, self._number)
_supports_INFO = False
_supports_EDIT = True
_supports_PARTITION = False
_supports_FORMAT = property(
lambda self: self.flag not in ('boot', 'bios_grub') and
self._constructed_device is None)
_supports_DELETE = property(
supported_actions = [
DeviceAction.EDIT,
DeviceAction.DELETE,
]
_can_EDIT = True
_can_DELETE = property(
lambda self: self.flag not in ('boot', 'bios_grub'))
_supports_MAKE_BOOT = False
@attr.s(cmp=False)
@ -417,14 +427,19 @@ class Raid(_Device):
def desc(self):
return _("software RAID {}").format(self.raidlevel)
_supports_INFO = False
_supports_EDIT = True
_supports_PARTITION = Disk._supports_PARTITION
_supports_FORMAT = property(
supported_actions = [
DeviceAction.EDIT,
DeviceAction.PARTITION,
DeviceAction.FORMAT,
DeviceAction.DELETE,
]
_can_EDIT = True
_can_PARTITION = Disk._can_PARTITION
_can_FORMAT = property(
lambda self: len(self._partitions) == 0 and
self._constructed_device is None)
_supports_DELETE = True
_supports_MAKE_BOOT = False
_can_DELETE = True
@property
def path(self):

View File

@ -32,7 +32,7 @@ from urwid import (
from subiquitycore.ui.actionmenu import (
Action,
ActionMenu,
ActionMenuButton,
ActionMenuOpenButton,
)
from subiquitycore.ui.buttons import (
back_btn,
@ -62,7 +62,10 @@ from subiquitycore.ui.utils import (
)
from subiquitycore.view import BaseView
from subiquity.models.filesystem import DeviceAction, humanize_size
from subiquity.models.filesystem import (
DeviceAction,
humanize_size,
)
from .delete import can_delete, ConfirmDeleteStretchy
from .disk_info import DiskInfoStretchy
@ -251,6 +254,7 @@ class MountList(WidgetWrap):
def _stretchy_shower(cls):
def impl(self, device):
self.parent.show_stretchy_overlay(cls(self.parent, device))
impl.opens_dialog = True
return impl
@ -287,7 +291,6 @@ class DeviceList(WidgetWrap):
_partition_EDIT = _stretchy_shower(
lambda parent, part: PartitionStretchy(parent, part.device, part))
_partition_DELETE = _stretchy_shower(ConfirmDeleteStretchy)
_partition_FORMAT = _disk_FORMAT
_raid_EDIT = _stretchy_shower(RaidStretchy)
_raid_PARTITION = _disk_PARTITION
@ -300,26 +303,29 @@ class DeviceList(WidgetWrap):
getattr(self, meth_name)(device)
def _action_menu_for_device(self, device):
if can_delete(device)[0]:
delete_btn = Color.danger_button(ActionMenuButton(_("Delete")))
else:
delete_btn = _("Delete *")
device_actions = [
(_("Information"), DeviceAction.INFO),
(_("Edit"), DeviceAction.EDIT),
(_("Add Partition"), DeviceAction.PARTITION),
(_("Format / Mount"), DeviceAction.FORMAT),
(delete_btn, DeviceAction.DELETE),
(_("Make boot device"), DeviceAction.MAKE_BOOT),
]
actions = []
for label, action in device_actions:
actions.append(Action(
device_actions = []
can_delete_device = can_delete(device)[0]
for action in device.supported_actions:
if action == DeviceAction.DELETE:
enabled = True
if can_delete_device:
label = Color.danger_button(
ActionMenuOpenButton(_("Delete")))
else:
label = _("Delete *")
else:
label = _(action.value)
enabled = device.action_possible(action)
meth_name = '_{}_{}'.format(device.type, action.name)
meth = getattr(self, meth_name)
opens_dialog = getattr(meth, 'opens_dialog', False)
device_actions.append(Action(
label=label,
enabled=device.supports_action(action),
enabled=enabled,
value=action,
opens_dialog=action != DeviceAction.MAKE_BOOT))
menu = ActionMenu(actions, "\N{BLACK RIGHT-POINTING SMALL TRIANGLE}")
opens_dialog=opens_dialog))
menu = ActionMenu(
device_actions, "\N{BLACK RIGHT-POINTING SMALL TRIANGLE}")
connect_signal(menu, 'action', self._action, device)
return menu

View File

@ -57,6 +57,7 @@ from subiquity.models.filesystem import (
DeviceAction,
get_raid_size,
humanize_size,
Partition,
raidlevels,
raidlevels_by_value,
)
@ -341,9 +342,19 @@ class RaidStretchy(Stretchy):
cur_devices = existing.devices | existing.spare_devices
def device_ok(dev):
return (dev not in omits
and (dev.supports_action(DeviceAction.FORMAT)
or dev in cur_devices))
if dev in omits:
return False
if dev in cur_devices:
return True
if dev.fs():
return False
if dev in cur_devices:
return True
if dev.constructed_device() is not None:
return False
if isinstance(dev, Partition):
return not dev.flag
return dev.action_possible(DeviceAction.FORMAT)
for dev in self.parent.model.all_devices():
if device_ok(dev):