When showing all the OSes, the list of distributions for some types of OSes (Linux, UNIX) will get insanely long, and thus very hard to scroll. As solution, introduce groups for some of the OS families, leaving the ones without a defined group into a "Others" group. To keep the completion working in the editable combobox, add a separate completion model for the completion entry, providing all the OSes directly there as simple list. There are a number of changes related to this: - the model for the OS comboboxes is now a TreeStore, and the iterations on the OS variant keep that into account - there are better UI labels for OS types and groups - when there are no groups for a type, add all the OSes directly, just like now - optimize the way types are added to the combobox: when not adding all of them, filter out those not "supported" - optimize the way OSes are added to the combobox: query only for the list we need (supported or all, not both), and group them according to the hash defined - add separator + "show all" options only when not showing all of them - _add_os_row now is called only when needed, so remove its "supported" parameter --- virtManager/create.py | 167 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 123 insertions(+), 44 deletions(-) diff --git a/virtManager/create.py b/virtManager/create.py index 83ddcba..ff4f1bb 100644 --- a/virtManager/create.py +++ b/virtManager/create.py @@ -304,6 +304,13 @@ class vmmCreate(vmmGObjectUI): cols.insert(OS_COL_LABEL, str) cols.insert(OS_COL_IS_SEP, bool) cols.insert(OS_COL_IS_SHOW_ALL, bool) + return Gtk.TreeStore(*cols) + + def make_completion_model(): + # [os value, os label] + cols = [] + cols.insert(OS_COL_ID, str) + cols.insert(OS_COL_LABEL, str) return Gtk.ListStore(*cols) # Lists for distro type + variant @@ -324,7 +331,7 @@ class vmmCreate(vmmGObjectUI): entry.set_completion(completion) completion.set_text_column(1) completion.set_inline_completion(True) - completion.set_model(os_variant_model) + completion.set_model(make_completion_model()) # Archtecture archList = self.widget("arch") @@ -930,18 +937,12 @@ class vmmCreate(vmmGObjectUI): # Helpers for populating OS type/variant UI # ############################################# - def _add_os_row(self, model, name="", label="", supported=False, - sep=False, action=False): + def _add_os_row(self, model, name="", label="", + sep=False, action=False, parent=None): """ Helper for building an os type/version row and adding it to the list model if necessary """ - visible = self._show_all_os_was_selected or supported - if sep or action: - visible = not self._show_all_os_was_selected - - if not visible: - return row = [] row.insert(OS_COL_ID, name) @@ -949,6 +950,12 @@ class vmmCreate(vmmGObjectUI): row.insert(OS_COL_IS_SEP, sep) row.insert(OS_COL_IS_SHOW_ALL, action) + return model.append(parent, row) + + def _add_completion_row(self, model, name, label): + row = [] + row.insert(OS_COL_ID, name) + row.insert(OS_COL_LABEL, label) model.append(row) def _populate_os_type_model(self): @@ -958,23 +965,40 @@ class vmmCreate(vmmGObjectUI): # Kind of a hack, just show linux + windows by default since # that's all 98% of people care about - supportl = ["generic", "linux", "windows"] + supported = {"generic", "linux", "windows"} # Move 'generic' to the front of the list types = virtinst.OSDB.list_types() types.remove("generic") types.insert(0, "generic") + # Pretty names for OSes. If a new OS is not found here, + # its capitalized name is used. + oses = { + "generic": _("Generic"), + "linux": _("Linux"), + "other": _("Others"), + "solaris": _("Solaris"), + "unix": _("UNIX"), + "windows": _("Windows"), + } + + # When only the "supported" types are requested, + # filter them. + if not self._show_all_os_was_selected: + types = [t for t in types if t in supported] + for typename in types: - supported = (typename in supportl) - typelabel = typename.capitalize() - if typename in ["unix"]: - typelabel = typename.upper() + try: + typelabel = oses[typename] + except KeyError: + typelabel = typename.capitalize() - self._add_os_row(model, typename, typelabel, supported) + self._add_os_row(model, typename, typelabel) - self._add_os_row(model, sep=True) - self._add_os_row(model, label=_("Show all OS options"), action=True) + if not self._show_all_os_was_selected: + self._add_os_row(model, sep=True) + self._add_os_row(model, label=_("Show all OS options"), action=True) # Select 'generic' by default widget.set_active(0) @@ -984,17 +1008,71 @@ class vmmCreate(vmmGObjectUI): model = widget.get_model() model.clear() - preferred = self.config.preferred_distros - variants = virtinst.OSDB.list_os(typename=_type, sortpref=preferred) - supportl = virtinst.OSDB.list_os(typename=_type, sortpref=preferred, - only_supported=True) + completion_model = self.widget("install-os-version-entry").get_completion().get_model() + completion_model.clear() - for v in variants: - supported = v in supportl or v.name == "generic" - self._add_os_row(model, v.name, v.label, supported) + preferred = self.config.preferred_distros - self._add_os_row(model, sep=True) - self._add_os_row(model, label=_("Show all OS options"), action=True) + # All the subgroups for top-level types. Distributions not + # belonging to these groups will be shown either in a "Others" + # group, or top-level if there are no other groups. + groups = { + "altlinux": _("ALT Linux"), + "centos": _("CentOS"), + "debian": _("Debian"), + "fedora": _("Fedora"), + "freebsd": _("FreeBSD"), + "mageia": _("Mageia"), + "netbsd": _("NetBSD"), + "openbsd": _("OpenBSD"), + "opensuse": _("openSUSE"), + "rhel": _("Red Hat Enterprise Linux"), + "sled": _("SUSE Linux Enterprise Desktop"), + "sles": _("SUSE Linux Enterprise Server"), + "ubuntu": _("Ubuntu"), + } + + if self._show_all_os_was_selected: + # List all the OSes, and determine which OSes have groups, + # and which do not. + variants = virtinst.OSDB.list_os(typename=_type, + sortpref=preferred) + all_distros = set([os.distro for os in variants]) + distros = [os for os in all_distros if os in groups] + distros.sort() + other_distros = [os for os in all_distros if os not in groups] + parents = dict() + if len(distros) > 0: + # We have groups for the OSes, so create them. + for d in distros: + parents[d] = self._add_os_row(model, "", groups[d]) + # Create the "Others" group at the end, for the OSes + # without a group. + if len(other_distros): + others_parent = self._add_os_row(model, "", _('Others')) + for d in other_distros: + parents[d] = others_parent + else: + # No groups, so assume the top-level will be the parent + # all the OSes. + for d in other_distros: + parents[d] = None + for v in variants: + self._add_os_row(model, v.name, v.label, + parent=parents[v.distro]) + self._add_completion_row(completion_model, v.name, v.label) + else: + # We are showing only the supported systems, so query them, + # and add them directly to their type. + variants = virtinst.OSDB.list_os(typename=_type, + sortpref=preferred, only_supported=True) + for v in variants: + self._add_os_row(model, v.name, v.label) + self._add_completion_row(completion_model, v.name, v.label) + + # Add the menu entries to show all the OSes + self._add_os_row(model, sep=True) + self._add_os_row(model, label=_("Show all OS options"), action=True) widget.set_active(0) @@ -1009,11 +1087,19 @@ class vmmCreate(vmmGObjectUI): """ model = os_widget.get_model() def find_row(): - for idx, row in enumerate(model): - if os_id and row[OS_COL_ID] == os_id: - os_widget.set_active(idx) - return row[OS_COL_LABEL] - os_widget.set_active(0) + def cmp_func(model, path, it, user_data): + ignore = path + if model.get_value(it, OS_COL_ID) == os_id: + os_widget.set_active_iter(it) + user_data[0] = model.get_value(it, OS_COL_LABEL) + return True + return False + data = [None] + model.foreach(cmp_func, data) + label = data[0] + if not label: + os_widget.set_active(0) + return label label = None if os_id: @@ -1166,33 +1252,26 @@ class vmmCreate(vmmGObjectUI): def _get_config_os_info(self): drow = uiutil.get_list_selected_row(self.widget("install-os-type")) - vrow = uiutil.get_list_selected_row(self.widget("install-os-version")) distro = None dlabel = None variant = None - variant_found = False - vlabel = self.widget("install-os-version-entry").get_text() + entry = self.widget("install-os-version-entry") + vlabel = entry.get_text() - for row in self.widget("install-os-version").get_model(): - if (not row[OS_COL_IS_SEP] and - not row[OS_COL_IS_SHOW_ALL] and - row[OS_COL_LABEL] == vlabel): + for row in entry.get_completion().get_model(): + if row[OS_COL_LABEL] == vlabel: variant = row[OS_COL_ID] - variant_found = True break - if vlabel and not variant_found: + if not variant: return (None, None, False, None, None) if drow: distro = drow[OS_COL_ID] dlabel = drow[OS_COL_LABEL] - if vrow: - variant = vrow[OS_COL_ID] - vlabel = vrow[OS_COL_LABEL] return (distro and str(distro), - variant and str(variant), + str(variant), True, str(dlabel), str(vlabel)) -- 2.9.3 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list