[gnome-boxes/refactor-thumbs: 3/5] views, thumbnails: Simplify our thumbnail widget




commit af6c46c1421b18dbe171236eee651e17abdb0567
Author: Felipe Borges <felipeborges gnome org>
Date:   Tue Jan 4 12:07:38 2022 +0100

    views, thumbnails: Simplify our thumbnail widget

 data/gnome-boxes.gresource.xml |  1 +
 data/gtk-style.css             | 10 -------
 data/ui/icon-view-child.ui     | 62 +++---------------------------------------
 data/ui/list-view-row.ui       | 44 ++++--------------------------
 data/ui/thumbnail.ui           | 42 ++++++++++++++++++++++++++++
 src/icon-view-child.vala       | 53 +++---------------------------------
 src/list-view-row.vala         | 57 ++++++--------------------------------
 src/machine-thumbnailer.vala   | 34 -----------------------
 src/meson.build                |  2 +-
 src/ui/thumbnail.vala          | 55 +++++++++++++++++++++++++++++++++++++
 10 files changed, 122 insertions(+), 238 deletions(-)
---
diff --git a/data/gnome-boxes.gresource.xml b/data/gnome-boxes.gresource.xml
index ab59b007..67bc4560 100644
--- a/data/gnome-boxes.gresource.xml
+++ b/data/gnome-boxes.gresource.xml
@@ -20,6 +20,7 @@
     <file preprocess="xml-stripblanks">ui/list-view-row.ui</file>
     <file preprocess="xml-stripblanks">ui/notification.ui</file>
     <file preprocess="xml-stripblanks">ui/searchbar.ui</file>
+    <file preprocess="xml-stripblanks">ui/thumbnail.ui</file>
     <file preprocess="xml-stripblanks">ui/topbar.ui</file>
     <file preprocess="xml-stripblanks">ui/transfer-info-row.ui</file>
     <file preprocess="xml-stripblanks">ui/transfer-popover.ui</file>
diff --git a/data/gtk-style.css b/data/gtk-style.css
index e5bb19f5..90b099c7 100644
--- a/data/gtk-style.css
+++ b/data/gtk-style.css
@@ -12,22 +12,12 @@
     background-image: none;
 }
 
-.slow-spinner {
-    animation-duration: 2s;
-}
-
 .thumbnail {
     background: @theme_bg_color;
     color: @theme_fg_color;
     border: 1px solid @borders;
 }
 
-.thumbnail.running {
-    background: black;
-    color: white;
-    border: none;
-}
-
 .boxes-product-key-entry {
     font-family: monospace;
 }
diff --git a/data/ui/icon-view-child.ui b/data/ui/icon-view-child.ui
index e4cb8894..95ade0ce 100644
--- a/data/ui/icon-view-child.ui
+++ b/data/ui/icon-view-child.ui
@@ -6,65 +6,11 @@
     <property name="orientation">vertical</property>
 
     <child>
-      <object class="GtkOverlay" id="overlay">
+      <object class="BoxesThumbnail" id="thumbnail">
         <property name="visible">True</property>
-
-        <child type="overlay">
-          <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="valign">end</property>
-            <property name="margin">10</property>
-            <property name="margin-start">20</property>
-            <property name="margin-end">20</property>
-          </object>
-        </child>
-
-        <child>
-          <object class="GtkStack" id="stack">
-            <property name="visible">True</property>
-            <child>
-              <object class="GtkImage" id="running_thumbnail">
-                <property name="visible">True</property>
-                <style>
-                  <class name="thumbnail"/>
-                  <class name="running"/>
-                </style>
-              </object>
-            </child>
-
-            <child>
-              <object class="GtkImage" id="thumbnail">
-                <property name="visible">True</property>
-                <property name="pixel-size">32</property>
-                <style>
-                  <class name="thumbnail"/>
-                </style>
-              </object>
-            </child>
-
-            <child>
-              <object class="GtkEventBox" id="spinner_box">
-                <property name="visible">True</property>
-                <child>
-                  <object class="GtkSpinner" id="spinner">
-                    <property name="visible">True</property>
-                    <property name="halign">center</property>
-                    <property name="valign">center</property>
-                    <property name="width-request">32</property>
-                    <property name="height-request">32</property>
-                    <style>
-                      <class name="slow-spinner"/>
-                    </style>
-                  </object>
-                </child>
-                <style>
-                  <class name="thumbnail"/>
-                </style>
-              </object>
-            </child>
-          </object>
-        </child>
-
+        <property name="emblem-size">5</property>
+        <property name="width-request">180</property>
+        <property name="height-request">134</property>
       </object>
     </child>
 
diff --git a/data/ui/list-view-row.ui b/data/ui/list-view-row.ui
index e1ab44ba..01776927 100644
--- a/data/ui/list-view-row.ui
+++ b/data/ui/list-view-row.ui
@@ -4,47 +4,15 @@
   <template class="BoxesListViewRow" parent="HdyActionRow">
     <property name="visible">True</property>
     <property name="margin">8</property>
+    <property name="activatable-widget">thumbnail</property>
 
     <child type="prefix">
-      <object class="GtkStack" id="stack">
+      <object class="BoxesThumbnail" id="thumbnail">
         <property name="visible">True</property>
-        <child>
-          <object class="GtkImage" id="running_thumbnail">
-            <property name="visible">True</property>
-            <style>
-              <class name="thumbnail"/>
-              <class name="running"/>
-            </style>
-          </object>
-        </child>
-
-        <child>
-          <object class="GtkImage" id="thumbnail">
-            <property name="visible">True</property>
-            <style>
-              <class name="thumbnail"/>
-            </style>
-          </object>
-        </child>
-
-        <child>
-          <object class="GtkEventBox" id="spinner_box">
-            <property name="visible">True</property>
-            <child>
-              <object class="GtkSpinner" id="spinner">
-                <property name="visible">True</property>
-                <property name="halign">center</property>
-                <property name="valign">center</property>
-                <style>
-                  <class name="slow-spinner"/>
-                </style>
-              </object>
-            </child>
-            <style>
-              <class name="thumbnail"/>
-            </style>
-          </object>
-        </child>
+        <property name="halign">start</property>
+        <property name="emblem-size">4</property>
+        <property name="width-request">60</property>
+        <property name="height-request">45</property>
       </object>
     </child>
   </template>
diff --git a/data/ui/thumbnail.ui b/data/ui/thumbnail.ui
new file mode 100644
index 00000000..ed7ae2c2
--- /dev/null
+++ b/data/ui/thumbnail.ui
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <template class="BoxesThumbnail" parent="GtkBox">
+    <style>
+      <class name="thumbnail"/>
+    </style>
+
+    <child>
+      <object class="GtkStack" id="stack">
+        <property name="visible">True</property>
+
+        <child>
+          <object class="GtkSpinner" id="spinner_thumbnail">
+            <property name="visible">True</property>
+            <property name="active">True</property>
+          </object>
+        </child>
+
+        <child>
+          <object class="GtkImage" id="live_thumbnail">
+            <property name="visible">True</property>
+          </object>
+        </child>
+
+        <child>
+          <object class="GtkBox" id="blank_thumbnail">
+            <property name="visible">True</property>
+
+            <child>
+              <object class="GtkImage" id="emblem">
+                <property name="visible">True</property>
+                <property name="hexpand">True</property>
+                <property name="halign">center</property>
+                <property name="icon-name">computer-symbolic</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/src/icon-view-child.vala b/src/icon-view-child.vala
index 699bf443..f55b4ef5 100644
--- a/src/icon-view-child.vala
+++ b/src/icon-view-child.vala
@@ -4,73 +4,28 @@
 
 [GtkTemplate (ui = "/org/gnome/Boxes/ui/icon-view-child.ui")]
 private class Boxes.IconViewChild : Gtk.Box {
-    public const int SCREENSHOT_WIDTH = 180;
-    public const int SCREENSHOT_HEIGHT = 134;
-
     public CollectionItem item { get; private set; }
     private Machine machine {
         get { return item as Machine; }
     }
 
     [GtkChild]
-    private unowned Gtk.Stack stack;
-    [GtkChild]
-    public unowned Gtk.Image thumbnail;
-    [GtkChild]
-    private unowned Gtk.EventBox spinner_box;
-    [GtkChild]
-    private unowned Gtk.Spinner spinner;
-    [GtkChild]
-    private unowned Gtk.Image running_thumbnail;
+    public unowned Boxes.Thumbnail thumbnail;
     [GtkChild]
     private unowned Gtk.Label machine_name;
 
-    private Boxes.MachineThumbnailer thumbnailer;
-
     public IconViewChild (CollectionItem item) {
         this.item = item;
 
-        thumbnailer = new MachineThumbnailer (machine,
-                                              SCREENSHOT_WIDTH,
-                                              SCREENSHOT_HEIGHT);
-
-        stack.width_request = SCREENSHOT_WIDTH;
-        stack.height_request = SCREENSHOT_HEIGHT;
-
+        update_thumbnail ();
         machine.notify["under-construction"].connect (update_thumbnail);
         machine.notify["is-stopped"].connect (update_thumbnail);
-        thumbnailer.notify["thumbnail"].connect (() => {
-            update_thumbnail ();
-        });
-
-        update_thumbnail ();
+        machine.notify["pixbuf"].connect (update_thumbnail);
 
         machine.bind_property ("name", machine_name, "label", BindingFlags.SYNC_CREATE);
     }
 
     private void update_thumbnail () {
-        var libvirt_machine = machine as LibvirtMachine;
-
-        running_thumbnail.set_from_pixbuf (thumbnailer.thumbnail);
-
-        if (machine.under_construction) {
-            stack.visible_child = spinner_box;
-            spinner.start ();
-
-            return;
-        } else if (thumbnailer.thumbnail != null) {
-            stack.visible_child = running_thumbnail;
-        } else {
-            if (VMConfigurator.is_live_config (libvirt_machine.domain_config))
-                thumbnail.icon_name = "media-optical-symbolic";
-            else if (machine.is_stopped)
-                thumbnail.icon_name = "system-shutdown-symbolic";
-            else
-                thumbnail.icon_name = "computer-symbolic";
-
-            stack.visible_child = thumbnail;
-        }
-
-        spinner.stop ();
+        thumbnail.update (machine);
     }
 }
diff --git a/src/list-view-row.vala b/src/list-view-row.vala
index 28e15462..f182b5b3 100644
--- a/src/list-view-row.vala
+++ b/src/list-view-row.vala
@@ -3,73 +3,34 @@
 
 [GtkTemplate (ui = "/org/gnome/Boxes/ui/list-view-row.ui")]
 private class Boxes.ListViewRow: Hdy.ActionRow {
-    public const int SCREENSHOT_WIDTH = 60;
-    public const int SCREENSHOT_HEIGHT = 45;
-
     public CollectionItem item { get; private set; }
     private Machine machine {
         get { return item as Machine; }
     }
 
     [GtkChild]
-    private unowned Gtk.Stack stack;
-    [GtkChild]
-    private unowned Gtk.Image thumbnail;
-    [GtkChild]
-    private unowned Gtk.Image running_thumbnail;
-    [GtkChild]
-    private unowned Gtk.EventBox spinner_box;
-    [GtkChild]
-    private unowned Gtk.Spinner spinner;
-
-    private Boxes.MachineThumbnailer thumbnailer;
+    public unowned Boxes.Thumbnail thumbnail;
 
     public ListViewRow (CollectionItem item) {
         this.item = item;
 
-        thumbnailer = new MachineThumbnailer (machine,
-                                              SCREENSHOT_WIDTH,
-                                              SCREENSHOT_HEIGHT);
-
-        stack.width_request = SCREENSHOT_WIDTH;
-        stack.height_request = SCREENSHOT_HEIGHT;
-
-        machine.notify["under-construction"].connect (update_thumbnail);
-        machine.notify["is-stopped"].connect (update_thumbnail);
+        update_status ();
         machine.notify["state"].connect (update_status);
         machine.notify["status"].connect (update_status);
-        thumbnailer.notify["thumbnail"].connect (update_thumbnail);
 
         update_thumbnail ();
-        update_status ();
+        machine.notify["under-construction"].connect (update_thumbnail);
+        machine.notify["is-stopped"].connect (update_thumbnail);
+        machine.notify["pixbuf"].connect (update_thumbnail);
 
         machine.bind_property ("name", this, "title", BindingFlags.SYNC_CREATE);
+
+        // This is a hack to align the "title" next to the "thumbnail".
+        activatable_widget.get_parent ().hexpand = false;
     }
 
     private void update_thumbnail () {
-        var libvirt_machine = machine as LibvirtMachine;
-
-        running_thumbnail.set_from_pixbuf (thumbnailer.thumbnail);
-
-        if (machine.under_construction) {
-            stack.visible_child = spinner_box;
-            spinner.start ();
-
-            return;
-        } else if (thumbnailer.thumbnail != null) {
-            stack.visible_child = running_thumbnail;
-        } else {
-            if (VMConfigurator.is_live_config (libvirt_machine.domain_config))
-                thumbnail.icon_name = "media-optical-symbolic";
-            else if (machine.is_stopped)
-                thumbnail.icon_name = "system-shutdown-symbolic";
-            else
-                thumbnail.icon_name = "computer-symbolic";
-
-            stack.visible_child = thumbnail;
-        }
-
-        spinner.stop ();
+        thumbnail.update (machine);
     }
 
     private void update_status () {
diff --git a/src/meson.build b/src/meson.build
index 3386b755..8ca050e7 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -66,7 +66,6 @@ vala_sources = [
   'list-view.vala',
   'list-view-row.vala',
   'machine.vala',
-  'machine-thumbnailer.vala',
   'main.vala',
   'media-manager.vala',
   'notification.vala',
@@ -80,6 +79,7 @@ vala_sources = [
   'troubleshoot-view.vala',
   'topbar.vala',
   'ui.vala',
+  'ui/thumbnail.vala', # FIXME: move this into ui/meson.build
   'unattended-installer.vala',
   'unattended-file.vala',
   'unattended-setup-box.vala',
diff --git a/src/ui/thumbnail.vala b/src/ui/thumbnail.vala
new file mode 100644
index 00000000..7105c690
--- /dev/null
+++ b/src/ui/thumbnail.vala
@@ -0,0 +1,55 @@
+// This file is part of GNOME Boxes. License: LGPLv2+
+
+[GtkTemplate (ui = "/org/gnome/Boxes/ui/thumbnail.ui")]
+private class Boxes.Thumbnail: Gtk.Box {
+    [GtkChild]
+    private unowned Gtk.Stack stack;
+    [GtkChild]
+    private unowned Gtk.Spinner spinner_thumbnail;
+    [GtkChild]
+    private unowned Gtk.Image live_thumbnail;
+    [GtkChild]
+    private unowned Gtk.Box blank_thumbnail;
+    [GtkChild]
+    private unowned Gtk.Image emblem;
+    private string emblem_icon_name {
+        set {
+            emblem.icon_name = value + "-symbolic";
+        }
+    }
+    public int emblem_size {
+        set {
+            emblem.icon_size = value;
+        }
+    }
+
+    public void update (Machine machine) {
+        if (machine.under_construction) {
+            stack.visible_child = spinner_thumbnail;
+
+            return;
+        }
+
+        if (machine.pixbuf != null && !machine.is_stopped) {
+            live_thumbnail.set_from_pixbuf (
+                machine.pixbuf.scale_simple (width_request,
+                                             height_request,
+                                             Gdk.InterpType.BILINEAR));
+            stack.visible_child = live_thumbnail;
+
+            return;
+        }
+
+        stack.visible_child = blank_thumbnail;
+        var libvirt_machine = machine as LibvirtMachine;
+        if (VMConfigurator.is_live_config (libvirt_machine.domain_config)) {
+            emblem_icon_name = "media-optical";
+        } else if (machine.is_stopped) {
+            emblem_icon_name = "system-shutdown";
+        } else {
+            emblem_icon_name = "computer";
+        }
+
+        debug ("Updating thumbnail!");
+    }
+}


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