[gnome-boxes/boxes-newbox-assistant-306] Downloads Hub WIP



commit 48599055ff365601d9b81f5453555bd18d5a8408
Author: Felipe Borges <felipeborges gnome org>
Date:   Mon Nov 18 16:50:51 2019 +0100

    Downloads Hub WIP

 data/gnome-boxes.gresource.xml        |  2 +
 data/ui/assistant/pages/index-page.ui |  2 +-
 data/ui/collection-toolbar.ui         | 27 +++++++++++
 data/ui/downloads-hub-row.ui          | 70 +++++++++++++++++++++++++++
 data/ui/downloads-hub.ui              | 16 +++++++
 src/app-window.vala                   |  6 +--
 src/assistant/downloads-page.vala     | 11 ++---
 src/assistant/index-page.vala         | 13 ++---
 src/assistant/vm-assistant.vala       | 28 +++++++++--
 src/collection-toolbar.vala           |  6 ++-
 src/downloads-hub.vala                | 90 +++++++++++++++++++++++++++++++++++
 src/meson.build                       |  1 +
 12 files changed, 247 insertions(+), 25 deletions(-)
---
diff --git a/data/gnome-boxes.gresource.xml b/data/gnome-boxes.gresource.xml
index 67dfbd8f..4db4ad80 100644
--- a/data/gnome-boxes.gresource.xml
+++ b/data/gnome-boxes.gresource.xml
@@ -13,6 +13,8 @@
     <file preprocess="xml-stripblanks">ui/collection-toolbar.ui</file>
     <file preprocess="xml-stripblanks">ui/display-page.ui</file>
     <file preprocess="xml-stripblanks">ui/display-toolbar.ui</file>
+    <file preprocess="xml-stripblanks">ui/downloads-hub.ui</file>
+    <file preprocess="xml-stripblanks">ui/downloads-hub-row.ui</file>
     <file preprocess="xml-stripblanks">ui/editable-entry.ui</file>
     <file preprocess="xml-stripblanks">ui/empty-boxes.ui</file>
     <file preprocess="xml-stripblanks">ui/icon-view.ui</file>
diff --git a/data/ui/assistant/pages/index-page.ui b/data/ui/assistant/pages/index-page.ui
index b400f1ab..d56fc25a 100644
--- a/data/ui/assistant/pages/index-page.ui
+++ b/data/ui/assistant/pages/index-page.ui
@@ -271,7 +271,7 @@
         <child>
           <object class="BoxesAssistantDownloadsPage" id="recommended_downloads_page">
             <property name="visible">True</property>
-            <signal name="media-selected" handler="on_download_selected"/>
+            <signal name="media-selected" handler="on_featured_media_selected"/>
           </object>
         </child>
 
diff --git a/data/ui/collection-toolbar.ui b/data/ui/collection-toolbar.ui
index ad117123..64516535 100644
--- a/data/ui/collection-toolbar.ui
+++ b/data/ui/collection-toolbar.ui
@@ -61,6 +61,33 @@
       </object>
     </child>
 
+    <child>
+      <object class="GtkMenuButton" id="downloads_hub_btn">
+        <property name="visible">False</property>
+        <property name="valign">center</property>
+        <property name="use-underline">True</property>
+        <style>
+          <class name="image-button"/>
+        </style>
+        <child internal-child="accessible">
+          <object class="AtkObject">
+            <property name="accessible-name" translatable="yes">Downloads</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkImage">
+            <property name="visible">True</property>
+            <property name="icon-name">media-record-symbolic</property>
+            <property name="icon-size">1</property>
+          </object>
+        </child>
+      </object>
+
+      <packing>
+        <property name="pack-type">end</property>
+      </packing>
+    </child>
+
     <child>
       <object class="GtkMenuButton" id="hamburger_btn">
         <property name="visible">True</property>
diff --git a/data/ui/downloads-hub-row.ui b/data/ui/downloads-hub-row.ui
new file mode 100644
index 00000000..daf6a026
--- /dev/null
+++ b/data/ui/downloads-hub-row.ui
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.19"/>
+  <template class="BoxesDownloadsHubRow" parent="GtkListBoxRow">
+    <property name="visible">True</property>
+    <property name="selectable">False</property>
+
+    <child>
+      <object class="GtkGrid">
+        <property name="visible">True</property>
+        <property name="border-width">10</property>
+        <property name="column-spacing">20</property>
+
+        <child>
+          <object class="GtkImage" id="image">
+            <property name="visible">True</property>
+            <property name="icon-name">media-optical</property>
+            <property name="icon-size">0</property>
+            <property name="pixel-size">64</property>
+          </object>
+          <packing>
+            <property name="height">2</property>
+            <property name="left-attach">0</property>
+          </packing>
+        </child>
+
+        <child>
+          <object class="GtkLabel" id="label">
+            <property name="visible">True</property>
+            <property name="wrap">True</property>
+            <property name="max-width-chars">40</property>
+            <property name="halign">start</property>
+          </object>
+          <packing>
+            <property name="left-attach">1</property>
+          </packing>
+        </child>
+
+        <child>
+          <object class="GtkProgressBar" id="progress_bar">
+            <property name="visible">True</property>
+            <property name="hexpand">True</property>
+          </object>
+          <packing>
+            <property name="left-attach">1</property>
+          </packing>
+        </child>
+
+        <child>
+          <object class="GtkButton">
+            <property name="visible">True</property>
+            <property name="valign">center</property>
+            <signal name="clicked" handler="cancel_download"/>
+
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="icon-name">window-close-symbolic</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left-attach">2</property>
+            <property name="height">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/data/ui/downloads-hub.ui b/data/ui/downloads-hub.ui
new file mode 100644
index 00000000..5d0665c2
--- /dev/null
+++ b/data/ui/downloads-hub.ui
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.19"/>
+  <template class="BoxesDownloadsHub" parent="GtkPopover">
+    <property name="can_focus">False</property>
+    <property name="modal">True</property>
+    <property name="position">bottom</property>
+
+    <child>
+      <object class="GtkListBox" id="listbox">
+        <property name="visible">True</property>
+        <signal name="row-activated" handler="on_row_activated"/>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/app-window.vala b/src/app-window.vala
index 51556afc..46d20ed4 100644
--- a/src/app-window.vala
+++ b/src/app-window.vala
@@ -232,7 +232,7 @@ private void ui_state_changed () {
                                             icon_view,
                                             list_view,
                                             props_window,
-                                            wizard_window,
+                                            //wizard_window,
                                             empty_boxes }) {
             ui.set_state (ui_state);
         }
@@ -303,8 +303,8 @@ public void show_remote_connection_assistant () {
         new Boxes.RemoteConnectionAssistant (this).run ();
     }
 
-    public void show_vm_assistant () {
-        new Boxes.VMAssistant (this).run ();
+    public void show_vm_assistant (string? path = null) {
+        new Boxes.VMAssistant (this, path).run ();
     }
 
     public void show_properties () {
diff --git a/src/assistant/downloads-page.vala b/src/assistant/downloads-page.vala
index 8872117b..a070ee9d 100644
--- a/src/assistant/downloads-page.vala
+++ b/src/assistant/downloads-page.vala
@@ -20,7 +20,7 @@
 
     private GLib.ListStore recommended_model;
 
-    public signal void media_selected (string url);
+    public signal void media_selected (Gtk.ListBoxRow row);
 
     private AssistantDownloadsPageView _page;
     public AssistantDownloadsPageView page {
@@ -74,17 +74,12 @@ private async void populate_recommended_list () {
     }
 
     private Gtk.Widget create_downloads_entry (Object item) {
-        var media = item as Osinfo.Media;
-
-        return new WizardDownloadableEntry (media);
+        return new WizardDownloadableEntry (item as Osinfo.Media);
     }
 
     [GtkCallback]
     private void on_listbox_row_activated (Gtk.ListBoxRow row) {
-        // Start to download Entry
-        var entry = row as WizardDownloadableEntry;
-
-        media_selected (entry.url);
+        media_selected (row);
     }
 
     [GtkCallback]
diff --git a/src/assistant/index-page.vala b/src/assistant/index-page.vala
index 7a39d3df..3883a7a3 100644
--- a/src/assistant/index-page.vala
+++ b/src/assistant/index-page.vala
@@ -42,7 +42,9 @@ public void setup (AppWindow app_window, VMAssistant dialog) {
 
     public void go_back () {
         if (stack.visible_child == home_page) {
-            dialog.close ();
+            dialog.shutdown ();
+
+            return;
         }
 
         stack.visible_child = home_page;
@@ -108,9 +110,9 @@ private void on_featured_media_selected (Gtk.ListBoxRow row) {
 
             rhel_dialog.run ();
         } else
-            on_download_selected (entry.url);
+            DownloadsHub.get_instance ().add_item (entry);
 
-        dialog.close ();
+        dialog.shutdown ();
     }
 
     public override void cleanup () {
@@ -137,9 +139,4 @@ private void on_download_an_os_button_clicked () {
 
         dialog.previous_button.label = _("Previous");
     }
-
-    [GtkCallback]
-    private void on_download_selected (string url) {
-        print (url);
-    }
 }
diff --git a/src/assistant/vm-assistant.vala b/src/assistant/vm-assistant.vala
index 164f1796..da2013e0 100644
--- a/src/assistant/vm-assistant.vala
+++ b/src/assistant/vm-assistant.vala
@@ -36,13 +36,31 @@
         use_header_bar = 1;
     }
 
-    public VMAssistant (AppWindow app_window) {
+    public VMAssistant (AppWindow app_window, string? uri = null) {
         set_transient_for (app_window);
 
         // TODO: Make the Assistant independent from window states
         app_window.set_state (UIState.WIZARD);
 
         index_page.setup (app_window, this);
+
+        // TODO: Rename this to PATH
+        if (uri != null)
+            prepare_for_uri.begin (uri);
+    }
+
+    private async void prepare_for_uri (string uri) {
+        var media_manager = MediaManager.get_instance ();
+
+        try {
+            var installer_media = yield media_manager.create_installer_media_for_path (uri, null);
+            do_preparation (installer_media);
+        } catch (GLib.Error error) {
+            debug("Failed to analyze installer image: %s", error.message);
+
+            var msg = _("Failed to analyze installer media. Corrupted or incomplete media?");
+            App.app.main_window.notificationbar.display_error (msg);
+        }
     }
 
     [GtkCallback]
@@ -114,17 +132,19 @@ private async void do_create (Object object) {
             vm_creator.launch_vm (machine);
         } catch (GLib.Error error) {
             warning ("Failed to create machine: %s", error.message);
+
+            // TODO: launch Notification
         }
 
         vm_creator.install_media.clean_up_preparation_cache ();
 
-        close ();
+        shutdown ();
     }
 
-    public override void close () {
+    public void shutdown () {
         // TODO: Make the Assistant independent from window states
         App.app.main_window.set_state (UIState.COLLECTION);
 
-        base.close ();
+        destroy ();
     }
 }
diff --git a/src/collection-toolbar.vala b/src/collection-toolbar.vala
index 2e337148..a2b2139f 100644
--- a/src/collection-toolbar.vala
+++ b/src/collection-toolbar.vala
@@ -16,6 +16,8 @@
     [GtkChild]
     private Button new_btn;
     [GtkChild]
+    private MenuButton downloads_hub_btn;
+    [GtkChild]
     private MenuButton hamburger_btn;
     [GtkChild]
     private CollectionFilterSwitcher filter_switcher;
@@ -46,6 +48,8 @@ public void setup_ui (AppWindow window) {
         var builder = new Builder.from_resource ("/org/gnome/Boxes/ui/menus.ui");
         MenuModel menu = (MenuModel) builder.get_object ("app-menu");
         hamburger_btn.popover = new Popover.from_model (hamburger_btn, menu);
+
+        downloads_hub_btn.popover = DownloadsHub.get_instance ();
     }
 
     public void click_back_button () {
@@ -62,7 +66,7 @@ public void click_search_button () {
 
     [GtkCallback]
     private void on_new_vm_btn_clicked () {
-        window.set_state (UIState.WIZARD);
+        //window.set_state (UIState.WIZARD);
     }
 
     [GtkCallback]
diff --git a/src/downloads-hub.vala b/src/downloads-hub.vala
new file mode 100644
index 00000000..f579c256
--- /dev/null
+++ b/src/downloads-hub.vala
@@ -0,0 +1,90 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+using Gtk;
+
+[GtkTemplate (ui = "/org/gnome/Boxes/ui/downloads-hub.ui")]
+private class Boxes.DownloadsHub : Gtk.Popover {
+    private static DownloadsHub instance;
+    public static DownloadsHub get_instance () {
+        if (instance == null)
+            instance = new DownloadsHub ();
+
+        return instance;
+    }
+
+    [GtkChild]
+    private ListBox listbox;
+
+    // TODO: inhibit suspend
+
+    public void add_item (WizardDownloadableEntry entry) {
+        var row = new DownloadsHubRow.from_entry (entry);
+
+        listbox.prepend (row);
+
+        if (!relative_to.visible)
+            relative_to.visible = true;
+
+        row.destroy.connect (() => {
+            if (listbox.get_children ().length () == 0)
+                relative_to.visible = false;
+        });
+
+        // TODO: notify download finished
+    }
+
+    [GtkCallback]
+    private void on_row_activated (Gtk.ListBoxRow _row) {
+        var row = _row as DownloadsHubRow;
+
+        if (row.local_file != null)
+            App.app.main_window.show_vm_assistant (row.local_file);
+    }
+}
+
+[GtkTemplate (ui= "/org/gnome/Boxes/ui/downloads-hub-row.ui")]
+private class Boxes.DownloadsHubRow : Gtk.ListBoxRow {
+    [GtkChild]
+    private Label label;
+    [GtkChild]
+    private Image image;
+    [GtkChild]
+    private ProgressBar progress_bar;
+
+    private ActivityProgress progress = new ActivityProgress ();
+    private ulong progress_notify_id;
+
+    private Cancellable cancellable = new Cancellable ();
+
+    public string? local_file;
+
+    public DownloadsHubRow.from_entry (WizardDownloadableEntry entry) {
+        label.label = entry.title;
+
+        Downloader.fetch_os_logo.begin (image, entry.os, 64);
+
+        progress_notify_id = progress.notify["progress"].connect (() => {
+            if (progress.progress - progress_bar.fraction >= 0.01)
+                progress_bar.fraction = progress.progress;
+        });
+        progress_bar.fraction = progress.progress = 0;
+
+        var soup_download_uri = new Soup.URI (entry.url);
+        var download_path = soup_download_uri.get_path ();
+
+        var filename = GLib.Path.get_basename (download_path);
+
+        download.begin (entry.url, filename);
+    }
+
+    private async void download (string url, string filename) {
+        local_file = yield Downloader.fetch_media (url, filename, progress, cancellable);
+    }
+
+    [GtkCallback]
+    private void cancel_download () {
+        progress.disconnect (progress_notify_id);
+        cancellable.cancel ();
+
+        destroy ();
+    }
+}
diff --git a/src/meson.build b/src/meson.build
index 4b741984..c78b8fbd 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -54,6 +54,7 @@ vala_sources = [
   'display-page.vala',
   'display-toolbar.vala',
   'display.vala',
+  'downloads-hub.vala',
   'editable-entry.vala',
   'i-properties-provider.vala',
   'i-collection-view.vala',


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]