[gnome-boxes/wip/exalm/light: 1/5] Clean up machine thumbnails




commit b52ed0a1140f4a5ec91d1805643dc2adbebac2f7
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Sat Dec 25 19:44:12 2021 +0500

    Clean up machine thumbnails

 data/gtk-style.css           |  23 +++++--
 data/ui/icon-view-child.ui   |  48 +++++++-------
 data/ui/list-view-row.ui     |  40 +++++-------
 src/icon-view-child.vala     |  47 +++++++++-----
 src/list-view-row.vala       |  40 +++++++-----
 src/machine-thumbnailer.vala | 145 +++----------------------------------------
 src/machine.vala             |   8 ---
 7 files changed, 119 insertions(+), 232 deletions(-)
---
diff --git a/data/gtk-style.css b/data/gtk-style.css
index d61c9be3..a6515b22 100644
--- a/data/gtk-style.css
+++ b/data/gtk-style.css
@@ -1,7 +1,3 @@
-@define-color boxes_bg_color shade (@theme_bg_color, 0.5);
-@define-color boxes_bg2_color mix (@theme_bg_color, @boxes_bg_color, 0.5);
-@define-color boxes_selected_color #3465a4;
-
 .boxes-snapshot-list-row.indicator {
     background-color: @insensitive_fg_color;
     border: none;
@@ -21,8 +17,23 @@
 }
 
 .thumbnail {
-    background: @boxes_bg2_color;
-    border: 1px solid @theme_bg_color;
+    background: @theme_bg_color;
+    color: @theme_fg_color;
+    border: 1px solid @borders;
+}
+
+.thumbnail.running {
+    background: black;
+    color: white;
+    border: none;
+}
+
+.favorite {
+  color: @theme_text_color;
+}
+
+.favorite.running {
+  color: white;
 }
 
 .boxes-product-key-entry {
diff --git a/data/ui/icon-view-child.ui b/data/ui/icon-view-child.ui
index 63c40936..c237437e 100644
--- a/data/ui/icon-view-child.ui
+++ b/data/ui/icon-view-child.ui
@@ -19,9 +19,11 @@
 
             <child>
               <object class="GtkImage" id="favorite">
-                <property name="visible">True</property>
-                <property name="width-request">16</property>
-                <property name="height-request">16</property>
+                <property name="visible">False</property>
+                <property name="icon-name">starred-symbolic</property>
+                <style>
+                  <class name="favorite"/>
+                </style>
               </object>
             </child>
 
@@ -42,48 +44,44 @@
           <object class="GtkStack" id="stack">
             <property name="visible">True</property>
             <child>
-              <object class="GtkImage" id="thumbnail">
+              <object class="GtkImage" id="running_thumbnail">
                 <property name="visible">True</property>
                 <style>
                   <class name="thumbnail"/>
+                  <class name="running"/>
                 </style>
               </object>
-
-              <packing>
-                <property name="name">thumbnail</property>
-              </packing>
             </child>
 
             <child>
-              <object class="GtkImage" id="live_thumbnail">
+              <object class="GtkImage" id="thumbnail">
                 <property name="visible">True</property>
-                <property name="icon-name">media-optical-symbolic</property>
-                <property name="icon-size">6</property>
+                <property name="pixel-size">32</property>
                 <style>
                   <class name="thumbnail"/>
                 </style>
               </object>
-
-              <packing>
-                <property name="name">live</property>
-              </packing>
             </child>
 
             <child>
-              <object class="GtkSpinner" id="spinner">
+              <object class="GtkEventBox" id="spinner_box">
                 <property name="visible">True</property>
-                <property name="height-request">8</property>
-                <property name="width-request">8</property>
-                <property name="halign">0.5</property>
-                <property name="valign">0.5</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="slow-spinner"/>
+                  <class name="thumbnail"/>
                 </style>
               </object>
-
-              <packing>
-                <property name="name">spinner</property>
-              </packing>
             </child>
           </object>
         </child>
diff --git a/data/ui/list-view-row.ui b/data/ui/list-view-row.ui
index 9e0a6a63..b0b7816d 100644
--- a/data/ui/list-view-row.ui
+++ b/data/ui/list-view-row.ui
@@ -25,48 +25,41 @@
       <object class="GtkStack" id="stack">
         <property name="visible">True</property>
         <child>
-          <object class="GtkImage" id="thumbnail">
+          <object class="GtkImage" id="running_thumbnail">
             <property name="visible">True</property>
             <style>
               <class name="thumbnail"/>
+              <class name="running"/>
             </style>
           </object>
-
-          <packing>
-            <property name="name">thumbnail</property>
-          </packing>
         </child>
 
         <child>
-          <object class="GtkImage" id="live_thumbnail">
+          <object class="GtkImage" id="thumbnail">
             <property name="visible">True</property>
-            <property name="icon-name">media-optical-symbolic</property>
-            <property name="icon-size">3</property>
             <style>
               <class name="thumbnail"/>
             </style>
           </object>
-
-          <packing>
-            <property name="name">live_thumbnail</property>
-          </packing>
         </child>
 
         <child>
-          <object class="GtkSpinner" id="spinner">
+          <object class="GtkEventBox" id="spinner_box">
             <property name="visible">True</property>
-            <property name="height-request">8</property>
-            <property name="width-request">8</property>
-            <property name="halign">0.5</property>
-            <property name="valign">0.5</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="slow-spinner"/>
+              <class name="thumbnail"/>
             </style>
           </object>
-
-          <packing>
-            <property name="name">spinner</property>
-          </packing>
         </child>
       </object>
 
@@ -79,8 +72,7 @@
     <child>
       <object class="GtkImage" id="favorite">
         <property name="visible">True</property>
-        <property name="width-request">16</property>
-        <property name="height-request">16</property>
+        <property name="icon-name">starred-symbolic</property>
       </object>
       <packing>
         <property name="expand">False</property>
diff --git a/src/icon-view-child.vala b/src/icon-view-child.vala
index dd9b4f38..0baf6eed 100644
--- a/src/icon-view-child.vala
+++ b/src/icon-view-child.vala
@@ -4,6 +4,9 @@
 
 [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 bool _selection_mode = false;
     public bool selection_mode {
         get { return _selection_mode; }
@@ -35,11 +38,13 @@
     [GtkChild]
     public unowned Gtk.Image thumbnail;
     [GtkChild]
+    private unowned Gtk.EventBox spinner_box;
+    [GtkChild]
     private unowned Gtk.Spinner spinner;
     [GtkChild]
     private unowned Gtk.Image favorite;
     [GtkChild]
-    private unowned Gtk.Image live_thumbnail;
+    private unowned Gtk.Image running_thumbnail;
     [GtkChild]
     private unowned Gtk.Label machine_name;
 
@@ -51,18 +56,22 @@
     public IconViewChild (CollectionItem item) {
         this.item = item;
 
-        thumbnailer = machine.thumbnailer;
+        thumbnailer = new MachineThumbnailer (machine,
+                                              SCREENSHOT_WIDTH,
+                                              SCREENSHOT_HEIGHT);
 
-        thumbnailer.favorite_emblem_enabled = false;
-        thumbnailer.notify["thumbnail"].connect (() => {
-            thumbnail.set_from_pixbuf (thumbnailer.thumbnail);
-        });
-        thumbnail.set_from_pixbuf (thumbnailer.thumbnail);
+        stack.width_request = SCREENSHOT_WIDTH;
+        stack.height_request = SCREENSHOT_HEIGHT;
 
         selected_binding = bind_property ("selected", selection_button, "active", 
BindingFlags.BIDIRECTIONAL);
 
         machine.config.notify["categories"].connect (update_favorite);
         machine.notify["under-construction"].connect (update_thumbnail);
+        machine.notify["is-stopped"].connect (update_thumbnail);
+        thumbnailer.notify["thumbnail"].connect (() => {
+            update_thumbnail ();
+            update_favorite ();
+        });
 
         update_thumbnail ();
         update_favorite ();
@@ -73,15 +82,23 @@ public IconViewChild (CollectionItem item) {
     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;
+            stack.visible_child = spinner_box;
             spinner.start ();
-            spinner.visible = true;
 
             return;
-        } else if (VMConfigurator.is_live_config (libvirt_machine.domain_config)) {
-            stack.visible_child = live_thumbnail;
+        } 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;
         }
 
@@ -89,9 +106,11 @@ private void update_thumbnail () {
     }
 
     private void update_favorite () {
-        if ("favorite" in machine.config.categories)
-            favorite.set_from_icon_name ("starred-symbolic", Gtk.IconSize.MENU);
+        favorite.visible = "favorite" in machine.config.categories;
+
+        if (thumbnailer.thumbnail != null)
+            favorite.get_style_context ().add_class ("running");
         else
-            favorite.clear ();
+            favorite.get_style_context ().remove_class ("running");
     }
 }
diff --git a/src/list-view-row.vala b/src/list-view-row.vala
index a26a1427..b58eb9e7 100644
--- a/src/list-view-row.vala
+++ b/src/list-view-row.vala
@@ -5,10 +5,6 @@
 private class Boxes.ListViewRow: Gtk.Box {
     public const int SCREENSHOT_WIDTH = 60;
     public const int SCREENSHOT_HEIGHT = 45;
-    public const int CENTERED_EMBLEM_SIZE = 16;
-    public const int EMBLEM_SIZE = 16;
-    public const Gdk.RGBA FRAME_BORDER_COLOR = { 0x81 / 255.0, 0x85 / 255.0, 0x84 / 255.0, 1.0 };
-    public const Gdk.RGBA FRAME_BACKGROUND_COLOR = { 0x4b / 255.0, 0x50 / 255.0, 0x50 / 255.0, 1.0 };
 
     public bool _selection_mode = false;
     public bool selection_mode {
@@ -41,7 +37,9 @@
     [GtkChild]
     private unowned Gtk.Image thumbnail;
     [GtkChild]
-    private unowned Gtk.Image live_thumbnail;
+    private unowned Gtk.Image running_thumbnail;
+    [GtkChild]
+    private unowned Gtk.EventBox spinner_box;
     [GtkChild]
     private unowned Gtk.Spinner spinner;
     [GtkChild]
@@ -60,22 +58,22 @@
     public ListViewRow (CollectionItem item) {
         this.item = item;
 
-        thumbnailer = new Boxes.MachineThumbnailer (machine,
-                                                    SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT,
-                                                    CENTERED_EMBLEM_SIZE, EMBLEM_SIZE);
-        thumbnailer.favorite_emblem_enabled = false;
-        thumbnailer.notify["thumbnail"].connect (() => {
-            thumbnail.set_from_pixbuf (thumbnailer.thumbnail);
-        });
-        thumbnail.set_from_pixbuf (thumbnailer.thumbnail);
+        thumbnailer = new MachineThumbnailer (machine,
+                                              SCREENSHOT_WIDTH,
+                                              SCREENSHOT_HEIGHT);
+
+        stack.width_request = SCREENSHOT_WIDTH;
+        stack.height_request = SCREENSHOT_HEIGHT;
 
         selected_binding = bind_property ("selected", selection_button, "active", 
BindingFlags.BIDIRECTIONAL);
 
         machine.config.notify["categories"].connect (update_favorite);
         machine.notify["under-construction"].connect (update_thumbnail);
+        machine.notify["is-stopped"].connect (update_thumbnail);
         machine.notify["info"].connect (update_info);
         machine.notify["state"].connect (update_status);
         machine.notify["status"].connect (update_status);
+        thumbnailer.notify["thumbnail"].connect (update_thumbnail);
 
         update_thumbnail ();
         update_favorite ();
@@ -88,15 +86,23 @@ public ListViewRow (CollectionItem item) {
     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;
+            stack.visible_child = spinner_box;
             spinner.start ();
-            spinner.visible = true;
 
             return;
-        } else if (VMConfigurator.is_live_config (libvirt_machine.domain_config)) {
-            stack.visible_child = live_thumbnail;
+        } 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;
         }
 
diff --git a/src/machine-thumbnailer.vala b/src/machine-thumbnailer.vala
index ceaa97f0..a0145b8f 100644
--- a/src/machine-thumbnailer.vala
+++ b/src/machine-thumbnailer.vala
@@ -1,165 +1,34 @@
 // This file is part of GNOME Boxes. License: LGPLv2+
 
 private class Boxes.MachineThumbnailer: Object {
-    private const Gtk.CornerType[] right_corners = { Gtk.CornerType.TOP_RIGHT, Gtk.CornerType.BOTTOM_RIGHT };
-    private const Gtk.CornerType[] bottom_corners = { Gtk.CornerType.BOTTOM_LEFT, 
Gtk.CornerType.BOTTOM_RIGHT };
-
-    public const double FRAME_RADIUS = 2.0;
-    public const Gdk.RGBA CENTERED_EMBLEM_COLOR = { 0xbe / 255.0, 0xbe / 255.0, 0xbe / 255.0, 1.0 };
-    public const Gdk.RGBA SMALL_EMBLEM_COLOR = { 1.0, 1.0, 1.0, 1.0 };
-    public const int EMBLEM_PADDING = 8;
-
     public weak Machine machine { get; private set; }
     public int width { get; set; }
     public int height { get; set; }
-    public int centred_emblem_size { get; set; }
-    public int emblem_size { get; set; }
-    public Gdk.RGBA border_color { get; set; }
-    public Gdk.RGBA background_color { get; set; }
-
-    public Gdk.Pixbuf thumbnail { get; private set; }
 
-    public bool favorite_emblem_enabled { get; set; default = true; }
+    public Gdk.Pixbuf? thumbnail { get; private set; }
 
-    public MachineThumbnailer (Machine machine,
-                               int width, int height,
-                               int centred_emblem_size, int emblem_size) {
+    public MachineThumbnailer (Machine machine, int width, int height) {
         this.machine = machine;
         this.width = width;
         this.height = height;
-        this.centred_emblem_size = centred_emblem_size;
-        this.emblem_size = emblem_size;
-        this.border_color = border_color;
-        this.background_color = background_color;
 
         machine.notify["pixbuf"].connect (() => {
             update_thumbnail ();
         });
-
-        machine.notify["under-construction"].connect (() => {
-            update_thumbnail ();
-        });
-
-        machine.config.notify["categories"].connect (() => {
+        machine.notify["is-stopped"].connect (() => {
             update_thumbnail ();
         });
 
         notify["width"].connect (update_thumbnail);
         notify["height"].connect (update_thumbnail);
-        notify["border-color"].connect (update_thumbnail);
-        notify["favorite-emblem-enabled"].connect (update_thumbnail);
-        notify["construction-spinner-enabled"].connect (update_thumbnail);
 
         update_thumbnail ();
     }
 
     private void update_thumbnail () {
-        Gdk.Pixbuf? new_thumbnail = null;
-
-        if (machine.is_stopped)
-            new_thumbnail = machine.under_construction ? get_under_construction_thumbnail () :
-                                                         get_stopped_thumbnail ();
-        else if (machine.pixbuf != null)
-            new_thumbnail = machine.pixbuf.scale_simple (width, height, Gdk.InterpType.BILINEAR);
-
-        // Use the default thumbnail if no thumbnail have been chosen
-        if (new_thumbnail == null)
-            new_thumbnail = get_default_thumbnail ();
-
-        if (favorite_emblem_enabled && "favorite" in machine.config.categories)
-            new_thumbnail = add_emblem_icon (new_thumbnail, "starred-symbolic", Gtk.CornerType.BOTTOM_LEFT);
-
-        thumbnail = new_thumbnail;
-    }
-
-    private Gdk.Pixbuf? empty_thumbnail;
-    private Gdk.Pixbuf get_empty_thumbnail () {
-        if (empty_thumbnail != null)
-            return empty_thumbnail;
-
-        empty_thumbnail = paint_empty_frame (width, height);
-
-        return empty_thumbnail;
-    }
-
-    private Gdk.Pixbuf? default_thumbnail;
-    private Gdk.Pixbuf get_default_thumbnail () {
-        if (default_thumbnail != null)
-            return default_thumbnail;
-
-        var frame = get_empty_thumbnail ();
-        default_thumbnail = add_centered_emblem_icon (frame, "computer-symbolic", centred_emblem_size);
-
-        return default_thumbnail;
-    }
-
-    private Gdk.Pixbuf? stopped_thumbnail;
-    private Gdk.Pixbuf get_stopped_thumbnail () {
-        if (stopped_thumbnail != null)
-            return stopped_thumbnail;
-
-        var frame = get_empty_thumbnail ();
-        stopped_thumbnail = add_centered_emblem_icon (frame, "system-shutdown-symbolic", 
centred_emblem_size);
-
-        return stopped_thumbnail;
-    }
-
-    private Gdk.Pixbuf get_under_construction_thumbnail () {
-        // If the machine is being constructed, it will draw a spinner itself, so we only need to draw an 
empty frame.
-        return get_empty_thumbnail ();
-    }
-
-    private Gdk.Pixbuf add_centered_emblem_icon (Gdk.Pixbuf pixbuf, string icon_name, int size) {
-        Gdk.Pixbuf? emblem = null;
-
-        var theme = Gtk.IconTheme.get_default ();
-        try {
-            var icon_info = theme.lookup_icon (icon_name, size, Gtk.IconLookupFlags.FORCE_SIZE);
-            emblem = icon_info.load_symbolic (CENTERED_EMBLEM_COLOR);
-        } catch (GLib.Error error) {
-            warning (@"Unable to get icon '$icon_name': $(error.message)");
-            return pixbuf;
-        }
-
-        if (emblem == null)
-            return pixbuf;
-
-        double offset_x = pixbuf.width / 2.0 - emblem.width / 2.0;
-        double offset_y = pixbuf.height / 2.0 - emblem.height / 2.0;
-
-        var emblemed = pixbuf.copy ();
-        emblem.composite (emblemed, (int) offset_x, (int) offset_y, size, size,
-                          offset_x, offset_y, 1.0, 1.0, Gdk.InterpType.BILINEAR, 255);
-
-        return emblemed;
-    }
-
-
-    private Gdk.Pixbuf add_emblem_icon (Gdk.Pixbuf pixbuf, string icon_name, Gtk.CornerType corner_type) {
-        Gdk.Pixbuf? emblem = null;
-
-        var theme = Gtk.IconTheme.get_default ();
-        try {
-            var icon_info = theme.lookup_icon (icon_name, emblem_size, Gtk.IconLookupFlags.FORCE_SIZE);
-            emblem = icon_info.load_symbolic (SMALL_EMBLEM_COLOR);
-        } catch (GLib.Error error) {
-            warning (@"Unable to get icon '$icon_name': $(error.message)");
-            return pixbuf;
-        }
-
-        if (emblem == null)
-            return pixbuf;
-
-        var offset_x = corner_type in right_corners ? pixbuf.width - emblem.width - EMBLEM_PADDING :
-                                                      EMBLEM_PADDING;
-
-        var offset_y = corner_type in bottom_corners ? pixbuf.height - emblem.height - EMBLEM_PADDING :
-                                                       EMBLEM_PADDING;
-
-        var emblemed = pixbuf.copy ();
-        emblem.composite (emblemed, offset_x, offset_y, emblem_size, emblem_size,
-                          offset_x, offset_y, 1.0, 1.0, Gdk.InterpType.BILINEAR, 255);
-
-        return emblemed;
+        if (!machine.is_stopped && machine.pixbuf != null)
+            thumbnail = machine.pixbuf.scale_simple (width, height, Gdk.InterpType.BILINEAR);
+        else
+            thumbnail = null;
     }
 }
diff --git a/src/machine.vala b/src/machine.vala
index 556406aa..0d78148d 100644
--- a/src/machine.vala
+++ b/src/machine.vala
@@ -8,7 +8,6 @@
     public Boxes.CollectionSource source;
     public Boxes.BoxConfig config;
     public Gdk.Pixbuf? pixbuf { get; set; }
-    public MachineThumbnailer thumbnailer { get; private set; }
     public bool stay_on_display;
     public string? info { get; protected set; }
     public string? status { get; set; }
@@ -75,8 +74,6 @@
     private uint screenshot_id;
     public const int SCREENSHOT_WIDTH = 180;
     public const int SCREENSHOT_HEIGHT = 134;
-    public const int CENTERED_EMBLEM_SIZE = 32;
-    public const int EMBLEM_SIZE = 16;
     private static Cairo.Surface grid_surface;
     private bool updating_screenshot;
     private uint autosave_timeout_id;
@@ -248,11 +245,6 @@ protected Machine (Boxes.CollectionSource source, string name, string? uuid = nu
 
         create_display_config (uuid);
 
-        // This needs to be set after the 'config' prop has been set.
-        thumbnailer = new MachineThumbnailer (this,
-                                              SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT,
-                                              CENTERED_EMBLEM_SIZE, EMBLEM_SIZE);
-
         notify["under-construction"].connect (() => {
             if (under_construction) {
                 var inhibit_reason = _("Machine is under construction");


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