Example #1
0
class MultiDeviceChooser(WidgetWrap, WantsToKnowFormField):
    signals = ['change']

    def __init__(self):
        self.table = TablePile([], spacing=1)
        self.device_to_checkbox = {}
        self.device_to_selector = {}
        self.devices = {}  # {device:active|spare}
        self.all_rows = []
        self.no_selector_rows = []
        self.supports_spares = True
        super().__init__(self.table)

    @property
    def value(self):
        return self.devices

    @value.setter
    def value(self, value):
        log.debug("MDC set value %s", {d.id: v for d, v in value.items()})
        self.devices = value
        for d, s in self.device_to_selector.items():
            if d in self.devices:
                s.enable()
                s.base_widget.value = self.devices[d]
            else:
                s.disable()
        for d, b in self.device_to_checkbox.items():
            b.set_state(d in self.devices)

    @property
    def active_devices(self):
        return {device for device, status in self.devices.items()
                if status == 'active'}

    @property
    def spare_devices(self):
        return {device for device, status in self.devices.items()
                if status == 'spare'}

    def set_supports_spares(self, val):
        if val == self.supports_spares:
            return
        self.supports_spares = val
        if val:
            for device in list(self.devices):
                self.device_to_selector[device].enable()
                selector = self.device_to_selector[device]
                self.devices[device] = selector.base_widget.value
            self.table.set_contents(self.all_rows)
        else:
            for device in list(self.devices):
                self.device_to_selector[device].disable()
                self.devices[device] = 'active'
            self.table.set_contents(self.no_selector_rows)

    def _state_change_device(self, sender, state, device):
        if state:
            if self.supports_spares:
                self.device_to_selector[device].enable()
            selector = self.device_to_selector[device]
            self.devices[device] = selector.base_widget.value
        else:
            self.device_to_selector[device].disable()
            del self.devices[device]
        self._emit('change', self.devices)

    def _select_active_spare(self, sender, value, device):
        self.devices[device] = value
        self._emit('change', self.devices)

    def _summarize(self, prefix, device):
        if device.fs() is not None:
            fs = device.fs()
            text = prefix + _("formatted as {}").format(fs.fstype)
            if fs.mount():
                text += _(", mounted at {}").format(fs.mount().path)
            else:
                text += _(", not mounted")
        else:
            text = prefix + _("unused {}").format(device.desc())
        return TableRow([(2, Color.info_minor(Text(text)))])

    def set_bound_form_field(self, bff):
        super().set_bound_form_field(bff)
        self.all_rows = []
        for kind, device in bff.form.all_devices:
            if kind == LABEL:
                self.all_rows.append(TableRow([
                    Text("    " + device.label),
                    Text(humanize_size(device.size), align='right')
                ]))
                self.no_selector_rows.append(self.all_rows[-1])
                self.all_rows.append(TableRow([
                    (2, Color.info_minor(Text("      " + device.desc())))
                ]))
                self.no_selector_rows.append(self.all_rows[-1])
            else:
                if kind == DEVICE:
                    label = device.label
                    prefix = "    "
                elif kind == PART:
                    label = _("  partition {}").format(device._number)
                    prefix = "      "
                else:
                    raise Exception("unexpected kind {}".format(kind))
                box = CheckBox(
                    label,
                    on_state_change=self._state_change_device,
                    user_data=device)
                self.device_to_checkbox[device] = box
                size = Text(humanize_size(device.size), align='right')
                self.all_rows.append(Color.menu_button(TableRow([box, size])))
                self.no_selector_rows.append(self.all_rows[-1])
                selector = Selector(['active', 'spare'])
                connect_signal(
                    selector, 'select', self._select_active_spare, device)
                selector = Toggleable(
                    UrwidPadding(
                        Color.menu_button(selector),
                        left=len(prefix)))
                selector.disable()
                self.device_to_selector[device] = selector
                self.all_rows.append(TableRow([(2, selector)]))
                # Do not append that one to no_selector_rows!
                self.all_rows.append(self._summarize(prefix, device))
                self.no_selector_rows.append(self.all_rows[-1])
        self.table.set_contents(self.all_rows)
        log.debug("%s", self.table._w.focus_position)
Example #2
0
class DeviceList(WidgetWrap):
    def __init__(self, parent, show_available):
        self.parent = parent
        self.show_available = show_available
        self.table = TablePile(
            [],
            spacing=2,
            colspecs={
                0: ColSpec(rpad=1),
                2: ColSpec(can_shrink=True),
                4: ColSpec(min_width=9),
                5: ColSpec(rpad=1),
            })
        if show_available:
            text = _("No available devices")
        else:
            text = _("No used devices")
        self._no_devices_content = Color.info_minor(Text(text))
        super().__init__(self.table)

    _disk_INFO = _stretchy_shower(DiskInfoStretchy)
    _disk_REFORMAT = _stretchy_shower(ConfirmReformatStretchy)
    _disk_PARTITION = _stretchy_shower(PartitionStretchy)
    _disk_FORMAT = _stretchy_shower(FormatEntireStretchy)

    def _disk_REMOVE(self, disk):
        cd = disk.constructed_device(skip_dm_crypt=False)
        if cd.type == "dm_crypt":
            self.parent.model.remove_dm_crypt(cd)
            disk, cd = cd, cd.constructed_device()
        if cd.type == "raid":
            if disk in cd.devices:
                cd.devices.remove(disk)
            else:
                cd.spare_devices.remove(disk)
        elif cd.type == "lvm_volgroup":
            cd.devices.remove(disk)
        else:
            1 / 0
        disk._constructed_device = None
        self.parent.refresh_model_inputs()

    def _disk_TOGGLE_BOOT(self, disk):
        if boot.is_boot_device(disk):
            self.parent.controller.remove_boot_disk(disk)
        else:
            self.parent.controller.add_boot_disk(disk)
        self.parent.refresh_model_inputs()

    _partition_EDIT = _stretchy_shower(
        lambda parent, part: PartitionStretchy(parent, part.device, part))
    _partition_REMOVE = _disk_REMOVE
    _partition_DELETE = _stretchy_shower(ConfirmDeleteStretchy)

    _raid_EDIT = _stretchy_shower(RaidStretchy)
    _raid_PARTITION = _disk_PARTITION
    _raid_FORMAT = _disk_FORMAT
    _raid_REFORMAT = _disk_REFORMAT
    _raid_REMOVE = _disk_REMOVE
    _raid_DELETE = _partition_DELETE

    _lvm_volgroup_EDIT = _stretchy_shower(VolGroupStretchy)
    _lvm_volgroup_CREATE_LV = _disk_PARTITION
    _lvm_volgroup_DELETE = _partition_DELETE

    _lvm_partition_EDIT = _stretchy_shower(
        lambda parent, part: PartitionStretchy(parent, part.volgroup, part))
    _lvm_partition_DELETE = _partition_DELETE

    def _action(self, sender, value, device):
        action, meth = value
        log.debug('_action %s %s', action, device.id)
        meth(device)

    def _label_REMOVE(self, action, device):
        cd = device.constructed_device()
        if cd:
            return _("Remove from {device}").format(device=labels.desc(cd))
        else:
            return action.str()

    def _label_PARTITION(self, action, device):
        return _("Add {ptype} Partition").format(
            ptype=device.ptable_for_new_partition().upper())

    def _label_TOGGLE_BOOT(self, action, device):
        if boot.is_boot_device(device):
            return _("Stop Using As Boot Device")
        else:
            if self.parent.controller.supports_resilient_boot:
                if boot.all_boot_devices(self.parent.model):
                    return _("Add As Another Boot Device")
            return _("Use As Boot Device")

    def _action_menu_for_device(self, device):
        device_actions = []
        for action in DeviceAction.supported(device):
            label_meth = getattr(self, '_label_{}'.format(action.name),
                                 lambda a, d: a.str())
            label = label_meth(action, device)
            enabled, whynot = action.can(device)
            if whynot:
                assert not enabled
                enabled = True
                label += " *"
                meth = _whynot_shower(self.parent, action, whynot)
            else:
                meth_name = '_{}_{}'.format(device.type, action.name)
                meth = getattr(self, meth_name)
            if not whynot and action in [
                    DeviceAction.DELETE, DeviceAction.REFORMAT
            ]:
                label = Color.danger_button(ActionMenuOpenButton(label))
            device_actions.append(
                Action(label=label,
                       enabled=enabled,
                       value=(action, meth),
                       opens_dialog=getattr(meth, 'opens_dialog', False)))
        menu = ActionMenu(device_actions)
        connect_signal(menu, 'action', self._action, device)
        return menu

    def refresh_model_inputs(self):
        devices = [
            d for d in self.parent.model.all_devices()
            if (d.available() == self.show_available or (
                not self.show_available and d.has_unavailable_partition()))
        ]
        if len(devices) == 0:
            self._w = Padding.push_2(self._no_devices_content)
            self.table.table_rows = []
            return
        self._w = self.table
        rows = []

        rows.append(
            Color.info_minor(
                TableRow([
                    Text(""),
                    (2, Text(_("DEVICE"))),
                    Text(_("TYPE")),
                    Text(_("SIZE"), align="center"),
                    Text(""),
                    Text(""),
                ])))
        for device in devices:
            for obj, cells in summarize_device(
                    device,
                    lambda part: part.available() == self.show_available):
                if obj is not None:
                    menu = self._action_menu_for_device(obj)
                else:
                    menu = Text("")
                if obj is device:
                    start, end = '[', ']'
                else:
                    start, end = '', ''
                cells = [Text(start)] + cells + [menu, Text(end)]
                if obj is not None:
                    rows.append(make_action_menu_row(cells, menu))
                else:
                    rows.append(TableRow(cells))
            if (self.show_available and device.used > 0
                    and device.free_for_partitions > 0):
                free = humanize_size(device.free_for_partitions)
                rows.append(
                    TableRow([
                        Text(""),
                        (3, Color.info_minor(Text(_("free space")))),
                        Text(free, align="right"),
                        Text(""),
                        Text(""),
                    ]))
            rows.append(TableRow([Text("")]))
        self.table.set_contents(rows[:-1])
        if self.table._w.focus_position >= len(rows):
            self.table._w.focus_position = len(rows) - 1
        while not self.table._w.focus.selectable():
            self.table._w.focus_position -= 1
Example #3
0
class MountList(WidgetWrap):
    def __init__(self, parent):
        self.parent = parent
        self.table = TablePile(
            [],
            spacing=2,
            colspecs={
                0: ColSpec(rpad=1),
                1: ColSpec(can_shrink=True),
                2: ColSpec(min_width=9),
                4: ColSpec(rpad=1),
                5: ColSpec(rpad=1),
            })
        self._no_mounts_content = Color.info_minor(
            Text(_("No disks or partitions mounted.")))
        super().__init__(self.table)

    def _mount_action(self, sender, action, mount):
        log.debug('_mount_action %s %s', action, mount)
        if action == 'unmount':
            self.parent.controller.delete_mount(mount)
            self.parent.refresh_model_inputs()

    def refresh_model_inputs(self):
        mountinfos = [
            MountInfo(mount=m)
            for m in sorted(self.parent.model.all_mounts(),
                            key=lambda m: (m.path == "", m.path))
        ]
        if len(mountinfos) == 0:
            self.table.set_contents([])
            self._w = Padding.push_2(self._no_mounts_content)
            return
        self._w = self.table

        rows = [
            TableRow([
                Color.info_minor(heading) for heading in [
                    Text(" "),
                    Text(_("MOUNT POINT")),
                    Text(_("SIZE"), align='center'),
                    Text(_("TYPE")),
                    Text(_("DEVICE TYPE")),
                    Text(" "),
                    Text(" "),
                ]
            ])
        ]

        for i, mi in enumerate(mountinfos):
            path_markup = mi.path
            if path_markup == "":
                path_markup = "SWAP"
            else:
                for j in range(i - 1, -1, -1):
                    mi2 = mountinfos[j]
                    if mi.startswith(mi2):
                        part1 = "/".join(mi.split_path[:len(mi2.split_path)])
                        part2 = "/".join([''] +
                                         mi.split_path[len(mi2.split_path):])
                        path_markup = [('info_minor', part1), part2]
                        break
                    if j == 0 and mi2.split_path == ['', '']:
                        path_markup = [
                            ('info_minor', "/"),
                            "/".join(mi.split_path[1:]),
                        ]
            actions = [(_("Unmount"), mi.mount.can_delete(), 'unmount')]
            menu = ActionMenu(actions)
            connect_signal(menu, 'action', self._mount_action, mi.mount)
            cells = [
                Text("["),
                Text(path_markup),
                Text(mi.size, align='right'),
                Text(mi.fstype),
                Text(mi.desc),
                menu,
                Text("]"),
            ]
            row = make_action_menu_row(cells,
                                       menu,
                                       attr_map='menu_button',
                                       focus_map={
                                           None: 'menu_button focus',
                                           'info_minor': 'menu_button focus',
                                       })
            rows.append(row)
        self.table.set_contents(rows)
        if self.table._w.focus_position >= len(rows):
            self.table._w.focus_position = len(rows) - 1
class DeviceList(WidgetWrap):

    def __init__(self, parent, show_available):
        self.parent = parent
        self.show_available = show_available
        self.table = TablePile([],  spacing=2, colspecs={
            0: ColSpec(rpad=1),
            1: ColSpec(can_shrink=True),
            2: ColSpec(min_width=9),
            3: ColSpec(rpad=1),
            4: ColSpec(rpad=1),
        })
        if show_available:
            text = _("No available devices")
        else:
            text = _("No used devices")
        self._no_devices_content = Color.info_minor(Text(text))
        super().__init__(self.table)

    _disk_INFO = _stretchy_shower(DiskInfoStretchy)
    _disk_PARTITION = _stretchy_shower(PartitionStretchy)
    _disk_FORMAT = _stretchy_shower(FormatEntireStretchy)

    def _disk_REMOVE(self, disk):
        cd = disk.constructed_device()
        if cd.type == "raid":
            if disk in cd.devices:
                cd.devices.remove(disk)
            else:
                cd.spare_devices.remove(disk)
        elif cd.type == "lvm_volgroup":
            cd.devices.remove(disk)
        else:
            1/0
        disk._constructed_device = None
        self.parent.refresh_model_inputs()

    def _disk_MAKE_BOOT(self, disk):
        self.parent.controller.make_boot_disk(disk)
        self.parent.refresh_model_inputs()

    _partition_EDIT = _stretchy_shower(
        lambda parent, part: PartitionStretchy(parent, part.device, part))
    _partition_REMOVE = _disk_REMOVE
    _partition_DELETE = _stretchy_shower(ConfirmDeleteStretchy)

    _raid_EDIT = _stretchy_shower(RaidStretchy)
    _raid_PARTITION = _disk_PARTITION
    _raid_FORMAT = _disk_FORMAT
    _raid_REMOVE = _disk_REMOVE
    _raid_DELETE = _partition_DELETE

    _lvm_volgroup_EDIT = _stretchy_shower(VolGroupStretchy)
    _lvm_volgroup_CREATE_LV = _disk_PARTITION
    _lvm_volgroup_DELETE = _partition_DELETE

    _lvm_partition_EDIT = _stretchy_shower(
        lambda parent, part: PartitionStretchy(parent, part.volgroup, part))
    _lvm_partition_DELETE = _partition_DELETE

    def _action(self, sender, value, device):
        action, meth = value
        log.debug('_action %s %s', action, device.id)
        meth(device)

    def _action_menu_for_device(self, device):
        device_actions = []
        for action in device.supported_actions:
            label = _(action.value)
            if action == DeviceAction.REMOVE and device.constructed_device():
                cd = device.constructed_device()
                label = _("Remove from {}").format(cd.desc())
            enabled, whynot = device.action_possible(action)
            if whynot:
                assert not enabled
                enabled = True
                label += " *"
                meth = _whynot_shower(self.parent, action, whynot)
            else:
                meth_name = '_{}_{}'.format(device.type, action.name)
                meth = getattr(self, meth_name)
            if not whynot and action == DeviceAction.DELETE:
                label = Color.danger_button(ActionMenuOpenButton(label))
            device_actions.append(Action(
                label=label,
                enabled=enabled,
                value=(action, meth),
                opens_dialog=getattr(meth, 'opens_dialog', False)))
        menu = ActionMenu(device_actions)
        connect_signal(menu, 'action', self._action, device)
        return menu

    def refresh_model_inputs(self):
        devices = [
            d for d in self.parent.model.all_devices()
            if (d.available() == self.show_available
                or (not self.show_available and d.has_unavailable_partition()))
        ]
        if len(devices) == 0:
            self._w = self._no_devices_content
            self.table.table_rows = []
            return
        self._w = self.table
        log.debug('FileSystemView: building device list')
        rows = []

        def _usage_label(obj):
            cd = obj.constructed_device()
            if cd is not None:
                return _("{component_name} of {name}").format(
                    component_name=cd.component_name, name=cd.name)
            fs = obj.fs()
            if fs is not None:
                m = fs.mount()
                if m:
                    return _(
                        "formatted as {fstype}, mounted at {path}").format(
                            fstype=fs.fstype, path=m.path)
                else:
                    return _("formatted as {fstype}, not mounted").format(
                        fstype=fs.fstype)
            else:
                return _("unused")

        rows.append(TableRow([Color.info_minor(heading) for heading in [
            Text(" "),
            Text(_("DEVICE")),
            Text(_("SIZE"), align="center"),
            Text(_("TYPE")),
            Text(" "),
            Text(" "),
        ]]))
        for device in devices:
            menu = self._action_menu_for_device(device)
            cells = [
                Text("["),
                Text(device.label),
                Text("{:>9}".format(humanize_size(device.size))),
                Text(device.desc()),
                menu,
                Text("]"),
            ]
            row = make_action_menu_row(cells, menu)
            rows.append(row)

            if not device.partitions():
                rows.append(TableRow([
                    Text(""),
                    (3, Text("  " + _usage_label(device))),
                    Text(""),
                    Text(""),
                ]))
            else:
                for part in device.partitions():
                    if part.available() != self.show_available:
                        continue
                    menu = self._action_menu_for_device(part)
                    part_size = "{:>9} ({}%)".format(
                        humanize_size(part.size),
                        int(100 * part.size / device.size))
                    cells = [
                        Text("["),
                        Text("  " + part.short_label),
                        (2, Text(part_size)),
                        menu,
                        Text("]"),
                    ]
                    row = make_action_menu_row(cells, menu, cursor_x=4)
                    rows.append(row)
                    if part.flag == "bios_grub":
                        label = "bios_grub"
                    else:
                        label = _usage_label(part)
                    rows.append(TableRow([
                        Text(""),
                        (3, Text("    " + label)),
                        Text(""),
                        Text(""),
                    ]))
                if (self.show_available
                        and device.used > 0
                        and device.free_for_partitions > 0):
                    size = device.size
                    free = device.free_for_partitions
                    percent = str(int(100 * free / size))
                    if percent == "0":
                        percent = "%.2f" % (100 * free / size,)
                    size_text = "{:>9} ({}%)".format(
                        humanize_size(free), percent)
                    rows.append(TableRow([
                        Text(""),
                        Text("  " + _("free space")),
                        (2, Text(size_text)),
                        Text(""),
                        Text(""),
                    ]))
        self.table.set_contents(rows)
        if self.table._w.focus_position >= len(rows):
            self.table._w.focus_position = len(rows) - 1
        while not self.table._w.focus.selectable():
            self.table._w.focus_position -= 1
Example #5
0
class DeviceList(WidgetWrap):
    def __init__(self, parent, show_available):
        self.parent = parent
        self.show_available = show_available
        self.table = TablePile(
            [],
            spacing=2,
            colspecs={
                0: ColSpec(rpad=1),
                1: ColSpec(can_shrink=True),
                2: ColSpec(min_width=9),
                3: ColSpec(rpad=1),
                4: ColSpec(rpad=1),
            })
        if show_available:
            text = _("No available devices")
        else:
            text = _("No used devices")
        self._no_devices_content = Color.info_minor(Text(text))
        super().__init__(self.table)
        self.refresh_model_inputs()
        # I don't really know why this is required:
        self.table._select_first_selectable()

    _disk_INFO = _stretchy_shower(DiskInfoStretchy)
    _disk_PARTITION = _stretchy_shower(PartitionStretchy)
    _disk_FORMAT = _stretchy_shower(FormatEntireStretchy)

    def _disk_MAKE_BOOT(self, disk):
        self.parent.controller.make_boot_disk(disk)
        self.parent.refresh_model_inputs()

    _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
    _raid_FORMAT = _disk_FORMAT
    _raid_DELETE = _partition_DELETE

    def _action(self, sender, action, device):
        log.debug('_action %s %s', action, device)
        meth_name = '_{}_{}'.format(device.type, action.name)
        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(label=label,
                       enabled=device.supports_action(action),
                       value=action,
                       opens_dialog=action != DeviceAction.MAKE_BOOT))
        menu = ActionMenu(actions, "\N{BLACK RIGHT-POINTING SMALL TRIANGLE}")
        connect_signal(menu, 'action', self._action, device)
        return menu

    def refresh_model_inputs(self):
        devices = [
            d for d in self.parent.model.all_devices()
            if (d.available() == self.show_available or (
                not self.show_available and d.has_unavailable_partition()))
        ]
        if len(devices) == 0:
            self._w = self._no_devices_content
            self.table.table_rows = []
            return
        self._w = self.table
        log.debug('FileSystemView: building device list')
        rows = []

        def _fmt_fs(label, fs):
            r = _("{} {}").format(label, fs.fstype)
            if not self.parent.model.fs_by_name[fs.fstype].is_mounted:
                return r
            m = fs.mount()
            if m:
                r += _(", {}").format(m.path)
            else:
                r += _(", not mounted")
            return r

        def _fmt_constructed(label, device):
            return _("{} part of {} ({})").format(label, device.label,
                                                  device.desc())

        rows.append(
            TableRow([
                Color.info_minor(heading) for heading in [
                    Text(" "),
                    Text(_("DEVICE")),
                    Text(_("SIZE"), align="center"),
                    Text(_("TYPE")),
                    Text(" "),
                    Text(" "),
                ]
            ]))
        for device in devices:
            menu = self._action_menu_for_device(device)
            row = TableRow([
                Text("["),
                Text(device.label),
                Text("{:>9}".format(humanize_size(device.size))),
                Text(device.desc()),
                menu,
                Text("]"),
            ])
            row = add_menu_row_focus_behaviour(menu, row, 'menu_button',
                                               'menu_button focus')
            rows.append(row)

            entire_label = None
            if device.fs():
                entire_label = _fmt_fs(
                    "    " + _("entire device formatted as"), device.fs())
            elif device.constructed_device():
                entire_label = _fmt_constructed("    " + _("entire device"),
                                                device.constructed_device())
            if entire_label is not None:
                rows.append(
                    TableRow([
                        Text(""),
                        (3, Text(entire_label)),
                        Text(""),
                        Text(""),
                    ]))
            else:
                for part in device.partitions():
                    if part.available() != self.show_available:
                        continue
                    prefix = _("partition {},").format(part._number)
                    if part.flag == "bios_grub":
                        label = prefix + " bios_grub"
                    elif part.fs():
                        label = _fmt_fs(prefix, part.fs())
                    elif part.constructed_device():
                        label = _fmt_constructed(prefix,
                                                 part.constructed_device())
                    else:
                        label = _("{} not formatted").format(prefix)
                    part_size = "{:>9} ({}%)".format(
                        humanize_size(part.size),
                        int(100 * part.size / device.size))
                    menu = self._action_menu_for_device(part)
                    row = TableRow([
                        Text("["),
                        Text("  " + label),
                        (2, Text(part_size)),
                        menu,
                        Text("]"),
                    ])
                    row = add_menu_row_focus_behaviour(menu,
                                                       row,
                                                       'menu_button',
                                                       'menu_button focus',
                                                       cursor_x=4)
                    rows.append(row)
                if (self.show_available and device.used > 0
                        and device.free_for_partitions > 0):
                    size = device.size
                    free = device.free_for_partitions
                    percent = str(int(100 * free / size))
                    if percent == "0":
                        percent = "%.2f" % (100 * free / size, )
                    size_text = "{:>9} ({}%)".format(humanize_size(free),
                                                     percent)
                    rows.append(
                        TableRow([
                            Text(""),
                            Text("  " + _("free space")),
                            (2, Text(size_text)),
                            Text(""),
                            Text(""),
                        ]))
        self.table.set_contents(rows)
        if self.table._w.focus_position >= len(rows):
            self.table._w.focus_position = len(rows) - 1
        while not self.table._w.focus.selectable():
            self.table._w.focus_position -= 1
Example #6
0
class ZdevList(WidgetWrap):
    def __init__(self, parent):
        self.parent = parent
        self.table = TablePile(
            [],
            spacing=2,
            colspecs={
                0: ColSpec(rpad=2),
                1: ColSpec(rpad=2),
                2: ColSpec(rpad=2),
                3: ColSpec(rpad=2),
            })
        self._no_zdev_content = Color.info_minor(
            Text(_("No zdev devices found.")))
        super().__init__(self.table)

    def _zdev_action(self, sender, action, zdevinfo):
        if action in ('disable', 'enable'):
            self.parent.controller.chzdev(action, zdevinfo)
            self.parent.refresh_model_inputs()

    def refresh_model_inputs(self):
        zdevinfos = self.parent.controller.get_zdevinfos()

        rows = [
            TableRow([
                Color.info_minor(heading) for heading in [
                    Text(_("ID")),
                    Text(_("ONLINE")),
                    Text(_("NAMES")),
                ]
            ])
        ]

        typeclass = ''
        for i, zdevinfo in enumerate(zdevinfos):
            if zdevinfo.typeclass != typeclass:
                rows.append(TableRow([
                    Text(""),
                ]))
                rows.append(
                    TableRow([
                        Color.info_minor(Text(zdevinfo.type)),
                        Text(""),
                        Text("")
                    ]))
                typeclass = zdevinfo.typeclass

            if zdevinfo.type == 'zfcp-lun':
                rows.append(
                    TableRow([
                        Color.info_minor(Text(zdevinfo.id[9:])),
                        zdevinfo.status,
                        Text(zdevinfo.names),
                    ]))
                continue

            actions = [(_("Enable"), not zdevinfo.on, 'enable'),
                       (_("Disable"), zdevinfo.on, 'disable')]
            menu = ActionMenu(actions)
            connect_signal(menu, 'action', self._zdev_action, zdevinfo)
            cells = [
                Text(zdevinfo.id),
                zdevinfo.status,
                Text(zdevinfo.names),
                menu,
            ]
            row = make_action_menu_row(cells,
                                       menu,
                                       attr_map='menu_button',
                                       focus_map={
                                           None: 'menu_button focus',
                                           'info_minor': 'menu_button focus',
                                       })
            rows.append(row)
        self.table.set_contents(rows)
        if self.table._w.focus_position >= len(rows):
            self.table._w.focus_position = len(rows) - 1