virt-manager/virtManager/oslist.py

104 lines
2.7 KiB
Python
Raw Normal View History

Redesign OS distro selection UI to be faster to use The current OS distro selection UI is fairly cumbersome to use. First you need to decide on a variant, then decide a distro and then look for the version you want. The list is filtered by default so only a subset of OS are displayed. So for less common distros you'll then need to start again and tell it to show all OS to try to find the one you want. The core problem is that we have an incredibly large list and want to make it easy for the user to find a specific entry. The modern UI paradigm for this problem is to provide interactive search with live updated results. The current UI does provide an interactive search facility on the OS version results, but you still have to first select a variant to be able to use the search which is unhelpful. This patch attempts to better apply the search UI design to the OS selection problem. We get rid of the notion of variants, distros and version, and provide a single text entry box in which the user can type a few letters of the OS name. As they type, a popover displays the matching results filtered on OS name. By default end of life OS will be hidden, so in general there will only be a small handful of results left after just typing a few characters. This makes it very quick to find and select the desired OS, without needing to provide a mutli-step navigation hierarchy. https://bugzilla.redhat.com/show_bug.cgi?id=1464306 Signed-off-by: Daniel P. Berrangé <berrange@redhat.com> (crobinso: fix some pylint)
2018-05-01 19:51:23 +08:00
# Copyright (C) 2018 Red Hat, Inc.
#
# This work is licensed under the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
from gi.repository import Gtk
import virtinst
from .baseclass import vmmGObjectUI
class vmmOSList(vmmGObjectUI):
__gsignals__ = {
"os-selected": (vmmGObjectUI.RUN_FIRST, None, [object])
}
def __init__(self):
vmmGObjectUI.__init__(self, "oslist.ui", "vmm-oslist")
self._cleanup_on_app_close()
self._filter_name = None
self._filter_eol = True
self.builder.connect_signals({
"on_include_eol_toggled": self._eol_toggled,
})
self._init_state()
def _init_state(self):
self.topwin.set_modal(False)
os_list = self.widget("os-list")
# (os object, label)
os_list_model = Gtk.ListStore(object, str)
all_os = virtinst.OSDB.list_os()
for os in all_os:
os_list_model.append([os, "%s (%s)" % (os.label, os.name)])
self._os_list_model = Gtk.TreeModelFilter(child_model=os_list_model)
self._os_list_model.set_visible_func(self._filter_os)
os_list.set_model(self._os_list_model)
nameCol = Gtk.TreeViewColumn(_("Name"))
nameCol.set_spacing(6)
text = Gtk.CellRendererText()
nameCol.pack_start(text, True)
nameCol.add_attribute(text, 'text', 1)
os_list.append_column(nameCol)
os_list.connect("row_activated", self._os_selected_cb)
def _eol_toggled(self, src):
self._filter_eol = not src.get_active()
self._refilter()
def _os_selected_cb(self, tree_view, path, column):
model, titer = tree_view.get_selection().get_selected()
if titer is None:
self.emit("os-selected", None)
else:
self.emit("os-selected", model[titer][0])
def _filter_os(self, model, titer, ignore1):
os = model.get(titer, 0)[0]
if self._filter_eol:
if os.eol:
return False
if self._filter_name is not None and self._filter_name != "":
label = os.label.lower()
name = os.name.lower()
if (label.find(self._filter_name) == -1 and
name.find(self._filter_name) == -1):
return False
return True
def _refilter(self):
os_list = self.widget("os-list")
sel = os_list.get_selection()
sel.unselect_all()
self._os_list_model.refilter()
def filter_name(self, partial_name):
self._filter_name = partial_name.lower()
self._refilter()
def show(self, parent):
self.topwin.set_relative_to(parent)
self.topwin.popup()
def hide(self):
self.topwin.popdown()
def _cleanup(self):
pass