From b874d9355644eb686a8af9df03884a0a19513059 Mon Sep 17 00:00:00 2001 From: Felipe Borges Date: Tue, 13 Nov 2018 14:26:12 +0100 Subject: [PATCH] wizard-downloads: Load recommended downloads from an XML file This way downstreams (vendors, distros) could easily tweak the list and offer the Osinfo downloads that they prefer, with the sorting they want. Cherry-picked from eb3af034b5cda6ce1fa6812624b531ea53f90f72 --- data/gnome-boxes.gresource.xml | 1 + data/recommended-downloads.xml | 18 +++++++ data/ui/wizard-source.ui | 1 - src/util-app.vala | 80 ++++++++++++++++++++++++++++ src/wizard-downloads-page.vala | 95 ++++++++++++++++++++++++++++++++++ src/wizard-source.vala | 33 ++++-------- 6 files changed, 204 insertions(+), 24 deletions(-) create mode 100644 data/recommended-downloads.xml create mode 100644 src/wizard-downloads-page.vala diff --git a/data/gnome-boxes.gresource.xml b/data/gnome-boxes.gresource.xml index 01c72d59..8a9b8b95 100644 --- a/data/gnome-boxes.gresource.xml +++ b/data/gnome-boxes.gresource.xml @@ -3,6 +3,7 @@ gtk-style.css ui/menus.ui + recommended-downloads.xml icons/boxes-arrow.svg icons/boxes-create.png icons/empty-boxes.png diff --git a/data/recommended-downloads.xml b/data/recommended-downloads.xml new file mode 100644 index 00000000..b389e945 --- /dev/null +++ b/data/recommended-downloads.xml @@ -0,0 +1,18 @@ + + + + http://redhat.com/rhel/7.6 + http://fedoraproject.org/fedora/29 + http://fedoraproject.org/silverblue/29 + http://ubuntu.com/ubuntu/18.10 + http://opensuse.org/opensuse/15.0 + http://debian.org/debian/9 + diff --git a/data/ui/wizard-source.ui b/data/ui/wizard-source.ui index b59fccfc..6762d2d6 100644 --- a/data/ui/wizard-source.ui +++ b/data/ui/wizard-source.ui @@ -49,7 +49,6 @@ False - diff --git a/src/util-app.vala b/src/util-app.vala index aba87cfd..253d1b74 100644 --- a/src/util-app.vala +++ b/src/util-app.vala @@ -102,6 +102,86 @@ public void fetch_os_logo (Gtk.Image image, Osinfo.Os os, int size) { } } + public string serialize_os_title (Osinfo.Media media) { + var title = "unknown"; + + /* Libosinfo lacks some OS variant names, so we do some + parsing here to compose a unique human-readable media + identifier. */ + var variant = ""; + var variants = media.get_os_variants (); + if (variants.get_length () > 0) + variant = (variants.get_nth (0) as Osinfo.OsVariant).get_name (); + else if ((media.os as Osinfo.Product).name != null) { + variant = (media.os as Osinfo.Product).name; + if (media.url != null && media.url.contains ("server")) + variant += " Server"; + } else { + var file = File.new_for_uri (media.url); + + title = file.get_basename ().replace ("_", ""); + } + + var subvariant = ""; + + if (media.url != null) { + if (media.url.contains ("netinst")) + subvariant = "(netinst)"; + else if (media.url.contains ("minimal")) + subvariant = "(minimal)"; + else if (media.url.contains ("dvd")) + subvariant = "(DVD)"; + } + + var is_live = media.live ? " (" + _("Live") + ")" : ""; + + title = @"$variant $(media.architecture) $subvariant $is_live"; + + /* Strip consequent whitespaces */ + return title.replace (" ", ""); + } + + public async GLib.List? get_recommended_downloads () { + uint8[] contents; + + try { + File file = File.new_for_uri ("resource:///org/gnome/Boxes/recommended-downloads.xml"); + + file.load_contents (null, out contents, null); + } catch (GLib.Error e) { + warning ("Failed to load recommended downloads file: %s", e.message); + + return null; + } + + Xml.Doc* doc = Xml.Parser.parse_doc ((string)contents); + if (doc == null) + return null; + + Xml.Node* root = doc->get_root_element (); + if (root == null || root->name != "list") { + warning ("Failed to parse recommended downloads"); + + return null; + } + + GLib.List list = new GLib.List (); + var os_db = MediaManager.get_instance ().os_db; + for (Xml.Node* iter = root->children; iter != null; iter = iter->next) { + var os_id = iter->get_content (); + try { + var os = yield os_db.get_os_by_id (os_id); + var media = os.get_media_list ().get_nth (0) as Osinfo.Media; + + list.append (media); + } catch (OSDatabaseError error) { + warning ("Failed to find OS with id: '%s': %s", os_id, error.message); + } + } + + return list; + } + public async GVir.StoragePool ensure_storage_pool (GVir.Connection connection) throws GLib.Error { var pool = get_storage_pool (connection); if (pool == null) { diff --git a/src/wizard-downloads-page.vala b/src/wizard-downloads-page.vala new file mode 100644 index 00000000..0b77a9cb --- /dev/null +++ b/src/wizard-downloads-page.vala @@ -0,0 +1,95 @@ +// This file is part of GNOME Boxes. License: LGPLv2+ + +public enum WizardDownloadsPageView { + RECOMMENDED, + SEARCH_RESULTS, + NO_RESULTS, +} + +public delegate void Boxes.DownloadChosenFunc (Boxes.WizardDownloadableEntry entry); + +[GtkTemplate (ui = "/org/gnome/Boxes/ui/wizard-downloads-page.ui")] +public class Boxes.WizardDownloadsPage : Gtk.Stack { + private OSDatabase os_db = new OSDatabase (); + public DownloadsSearch search { private set; get; } + + public DownloadChosenFunc download_chosen_func; + + [GtkChild] + private Gtk.ListBox listbox; + [GtkChild] + private Gtk.ListBox recommended_listbox; + + private GLib.ListStore recommended_model; + + private WizardDownloadsPageView _page; + public WizardDownloadsPageView page { + get { return _page; } + set { + _page = value; + + switch (_page) { + case WizardDownloadsPageView.SEARCH_RESULTS: + visible_child_name = "search-results"; + break; + case WizardDownloadsPageView.NO_RESULTS: + visible_child_name = "no-results"; + break; + case WizardDownloadsPageView.RECOMMENDED: + default: + visible_child_name = "recommended"; + break; + } + } + } + + construct { + os_db.load.begin (); + + search = new DownloadsSearch (); + + recommended_model = new GLib.ListStore (typeof (Osinfo.Media)); + recommended_listbox.bind_model (recommended_model, create_downloads_entry); + populate_recommended_list.begin (); + + listbox.bind_model (search.model, create_downloads_entry); + + search.search_changed.connect (set_visible_view); + } + + private void set_visible_view () { + if (search.text.length == 0) { + page = WizardDownloadsPageView.RECOMMENDED; + } else if (search.model.get_n_items () == 0) { + page = WizardDownloadsPageView.NO_RESULTS; + } else { + page = WizardDownloadsPageView.SEARCH_RESULTS; + } + } + + private async void populate_recommended_list () { + foreach (var media in yield get_recommended_downloads ()) { + recommended_model.append (media); + } + } + + private Gtk.Widget create_downloads_entry (Object item) { + var media = item as Osinfo.Media; + + return new WizardDownloadableEntry (media); + } + + [GtkCallback] + private void on_listbox_row_activated (Gtk.ListBoxRow row) { + var entry = row as WizardDownloadableEntry; + + download_chosen_func (entry); + } + + [GtkCallback] + private void on_show_more_button_clicked () { + search.show_all (); + + page = WizardDownloadsPageView.SEARCH_RESULTS; + } +} diff --git a/src/wizard-source.vala b/src/wizard-source.vala index 9ea0a9b1..494c5561 100644 --- a/src/wizard-source.vala +++ b/src/wizard-source.vala @@ -310,6 +310,7 @@ private void on_notify_estimated_load_progress () { private Gtk.ListBox media_vbox; private Gtk.ListBox downloads_vbox; + private GLib.ListStore downloads_model; private Osinfo.Os rhel_os; private Cancellable? rhel_cancellable; @@ -318,12 +319,6 @@ private void on_notify_estimated_load_progress () { public string filename { get; set; } - private string[] recommended_downloads = { - "http://ubuntu.com/ubuntu/16.04", - "http://opensuse.org/opensuse/42.2", - "http://fedoraproject.org/fedora/27", - }; - public bool download_required { get { string scheme = Uri.parse_scheme (uri); @@ -409,6 +404,8 @@ private void on_notify_estimated_load_progress () { } }); + downloads_model = new GLib.ListStore (typeof (Osinfo.Media)); + rhel_web_view.view.decide_policy.connect (on_rhel_web_view_decide_policy); } @@ -425,26 +422,16 @@ public void setup_ui (AppWindow window) { assert (window != null); this.window = window; + + downloads_vbox.bind_model (downloads_model, create_downloadable_entry); + + populate_recommended_downloads.begin (); } - [GtkCallback] - private void on_downloads_scrolled_shown () { + private async void populate_recommended_downloads () { var os_db = media_manager.os_db; - foreach (var os_id in recommended_downloads) { - os_db.get_os_by_id.begin (os_id, (obj, res) => { - try { - var os = os_db.get_os_by_id.end (res); - - // TODO: Select the desktop/workstation variant. - var media = os.get_media_list ().get_nth (0) as Osinfo.Media; - var entry = create_downloadable_entry (media); - - downloads_vbox.insert (entry, -1); - } catch (OSDatabaseError error) { - warning ("Failed to find OS with ID '%s': %s", os_id, error.message); - return; - } - }); + foreach (var media in yield get_recommended_downloads ()) { + downloads_model.append (media); } } -- 2.19.2