[gnome-software: 19/29] gs-page: Expose update/installed counter as GsPage:counter




commit b49f9d31d249ba20ea24451c132e47151063a14d
Author: Philip Withnall <pwithnall endlessos org>
Date:   Thu Jan 21 13:27:18 2021 +0000

    gs-page: Expose update/installed counter as GsPage:counter
    
    Then bind that to the counter labels in the buttonbox at the top of the
    shell. This fixes a layering violation where the installed and updates
    page would update shell widgets directly themselves.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>

 src/gs-installed-page.c | 16 +++++-----------
 src/gs-page.c           | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 src/gs-page.h           |  1 +
 src/gs-shell.c          | 42 ++++++++++++++++++++++++++++++++++++++++++
 src/gs-updates-page.c   | 45 +++++++++++++++++++--------------------------
 5 files changed, 111 insertions(+), 38 deletions(-)
---
diff --git a/src/gs-installed-page.c b/src/gs-installed-page.c
index eb623b6c8..6aee85c10 100644
--- a/src/gs-installed-page.c
+++ b/src/gs-installed-page.c
@@ -34,6 +34,7 @@ struct _GsInstalledPage
        gboolean                 waiting;
        GsShell                 *shell;
        GSettings               *settings;
+       guint                    pending_apps_counter;
 
        GtkWidget               *list_box_install;
        GtkWidget               *scrolledwindow_install;
@@ -535,7 +536,6 @@ gs_installed_page_pending_apps_changed_cb (GsPluginLoader *plugin_loader,
                                            GsInstalledPage *self)
 {
        GsApp *app;
-       GtkWidget *widget;
        guint i;
        guint cnt = 0;
        g_autoptr(GsAppList) pending = NULL;
@@ -558,16 +558,10 @@ gs_installed_page_pending_apps_changed_cb (GsPluginLoader *plugin_loader,
                cnt++;
        }
 
-       /* show a label with the number of on-going operations */
-       widget = GTK_WIDGET (gtk_builder_get_object (self->builder,
-                                                    "button_installed_counter"));
-       if (cnt == 0) {
-               gtk_widget_hide (widget);
-       } else {
-               g_autofree gchar *label = NULL;
-               label = g_strdup_printf ("%u", cnt);
-               gtk_label_set_label (GTK_LABEL (widget), label);
-               gtk_widget_show (widget);
+       /* update the number of on-going operations */
+       if (cnt != self->pending_apps_counter) {
+               self->pending_apps_counter = cnt;
+               g_object_notify (G_OBJECT (self), "counter");
        }
 }
 
diff --git a/src/gs-page.c b/src/gs-page.c
index 8adba6f96..b375d60bd 100644
--- a/src/gs-page.c
+++ b/src/gs-page.c
@@ -30,9 +30,10 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GsPage, gs_page, GTK_TYPE_BIN)
 
 typedef enum {
        PROP_TITLE = 1,
+       PROP_COUNTER,
 } GsPageProperty;
 
-static GParamSpec *obj_props[PROP_TITLE + 1] = { NULL, };
+static GParamSpec *obj_props[PROP_COUNTER + 1] = { NULL, };
 
 GsShell *
 gs_page_get_shell (GsPage *page)
@@ -624,6 +625,31 @@ gs_page_get_title (GsPage *page)
        return g_value_get_string (&value);
 }
 
+/**
+ * gs_page_get_counter:
+ * @page: a #GsPage
+ *
+ * Get the value of #GsPage:counter.
+ *
+ * Returns: a counter of the number of available updates, installed packages,
+ *     etc. on this page
+ *
+ * Since: 40
+ */
+guint
+gs_page_get_counter (GsPage *page)
+{
+       g_auto(GValue) value = G_VALUE_INIT;
+
+       g_return_val_if_fail (GS_IS_PAGE (page), 0);
+
+       /* The property is typically overridden by subclasses; the
+        * implementation in #GsPage itself is just a placeholder. */
+       g_object_get_property (G_OBJECT (page), "counter", &value);
+
+       return g_value_get_uint (&value);
+}
+
 /**
  * gs_page_switch_to:
  *
@@ -721,6 +747,10 @@ gs_page_get_property (GObject    *object,
                /* Should be overridden by subclasses. */
                g_value_set_string (value, NULL);
                break;
+       case PROP_COUNTER:
+               /* Should be overridden by subclasses. */
+               g_value_set_uint (value, 0);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -766,6 +796,19 @@ gs_page_class_init (GsPageClass *klass)
                                     NULL,
                                     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
+       /**
+        * GsPage:counter:
+        *
+        * A counter indicating the number of installed packages, available
+        * updates, etc. on this page.
+        *
+        * Since: 40
+        */
+       obj_props[PROP_COUNTER] =
+               g_param_spec_uint ("counter", NULL, NULL,
+                                  0, G_MAXUINT, 0,
+                                  G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
        g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props);
 }
 
diff --git a/src/gs-page.h b/src/gs-page.h
index aba930a52..108c87e25 100644
--- a/src/gs-page.h
+++ b/src/gs-page.h
@@ -76,5 +76,6 @@ gboolean       gs_page_setup                          (GsPage         *page,
 gboolean        gs_page_is_active                      (GsPage         *page);
 
 const gchar    *gs_page_get_title                      (GsPage         *page);
+guint           gs_page_get_counter                    (GsPage         *page);
 
 G_END_DECLS
diff --git a/src/gs-shell.c b/src/gs-shell.c
index aac0ce36f..5ea1c9bea 100644
--- a/src/gs-shell.c
+++ b/src/gs-shell.c
@@ -76,6 +76,8 @@ struct _GsShell
        GsPage                  *page;
 
        GBinding                *application_details_header_binding;
+       GBinding                *button_installed_counter_binding;
+       GBinding                *button_updates_counter_binding;
 
 #ifdef HAVE_MOGWAI
        MwscScheduler           *scheduler;
@@ -2093,6 +2095,29 @@ gs_shell_close_window_accel_cb (GtkAccelGroup *accel_group,
        return TRUE;
 }
 
+static void
+counter_notify_label_cb (GObject    *obj,
+                         GParamSpec *pspec,
+                         gpointer    user_data)
+{
+       GtkLabel *label = GTK_LABEL (obj);
+       GsShell *shell = GS_SHELL (user_data);
+       gboolean is_interesting;
+
+       /* hide the label if its value is not useful to the user */
+       is_interesting = (g_strcmp0 (gtk_label_get_label (label), "") != 0 &&
+                         g_strcmp0 (gtk_label_get_label (label), "0") != 0);
+
+       gtk_widget_set_visible (GTK_WIDGET (label), is_interesting);
+
+       /* update the tab style */
+       if (is_interesting &&
+           gs_shell_get_mode (shell) != GS_SHELL_MODE_UPDATES)
+               gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (label)), 
"needs-attention");
+       else
+               gtk_style_context_remove_class (gtk_widget_get_style_context (GTK_WIDGET (label)), 
"needs-attention");
+}
+
 void
 gs_shell_setup (GsShell *shell, GsPluginLoader *plugin_loader, GCancellable *cancellable)
 {
@@ -2253,6 +2278,21 @@ gs_shell_setup (GsShell *shell, GsPluginLoader *plugin_loader, GCancellable *can
                g_signal_connect (widget, "search-changed",
                                  G_CALLBACK (search_changed_handler), shell);
 
+       /* bind the counters */
+       widget = GTK_WIDGET (gtk_builder_get_object (shell->builder, "button_installed_counter"));
+       page = g_hash_table_lookup (shell->pages, "installed");
+       shell->button_installed_counter_binding = g_object_bind_property (page, "counter",
+                                                                         widget, "label",
+                                                                         G_BINDING_SYNC_CREATE);
+       g_signal_connect (widget, "notify::label", G_CALLBACK (counter_notify_label_cb), shell);
+
+       widget = GTK_WIDGET (gtk_builder_get_object (shell->builder, "button_updates_counter"));
+       page = g_hash_table_lookup (shell->pages, "updates");
+       shell->button_updates_counter_binding = g_object_bind_property (page, "counter",
+                                                                       widget, "label",
+                                                                       G_BINDING_SYNC_CREATE);
+       g_signal_connect (widget, "notify::label", G_CALLBACK (counter_notify_label_cb), shell);
+
        /* load content */
        page = GS_PAGE (gtk_builder_get_object (shell->builder, "loading_page"));
        g_signal_connect (page, "refreshed",
@@ -2438,6 +2478,8 @@ gs_shell_dispose (GObject *object)
        GsShell *shell = GS_SHELL (object);
 
        g_clear_object (&shell->application_details_header_binding);
+       g_clear_object (&shell->button_installed_counter_binding);
+       g_clear_object (&shell->button_updates_counter_binding);
 
        if (shell->back_entry_stack != NULL) {
                g_queue_free_full (shell->back_entry_stack, (GDestroyNotify) free_back_entry);
diff --git a/src/gs-updates-page.c b/src/gs-updates-page.c
index 8ac643c1e..5f849733e 100644
--- a/src/gs-updates-page.c
+++ b/src/gs-updates-page.c
@@ -64,6 +64,7 @@ struct _GsUpdatesPage
        GtkWidget               *header_end_box;
        gboolean                 has_agreed_to_mobile_data;
        gboolean                 ampm_available;
+       guint                    updates_counter;
 
        GtkWidget               *updates_box;
        GtkWidget               *button_updates_mobile;
@@ -104,6 +105,7 @@ typedef enum {
        PROP_HSCROLL_POLICY,
        PROP_VSCROLL_POLICY,
        PROP_TITLE,
+       PROP_COUNTER,
 } GsUpdatesPageProperty;
 
 static void
@@ -201,29 +203,18 @@ gs_updates_page_get_state_string (GsPluginStatus status)
 static void
 refresh_headerbar_updates_counter (GsUpdatesPage *self)
 {
-       GtkWidget *widget;
-       guint num_updates;
-
-       num_updates = _get_num_updates (self);
-
-       /* update the counter */
-       widget = GTK_WIDGET (gtk_builder_get_object (self->builder, "button_updates_counter"));
-       if (num_updates > 0 &&
-           gs_plugin_loader_get_allow_updates (self->plugin_loader)) {
-               g_autofree gchar *text = NULL;
-               text = g_strdup_printf ("%u", num_updates);
-               gtk_label_set_label (GTK_LABEL (widget), text);
-               gtk_widget_show (widget);
-       } else {
-               gtk_widget_hide (widget);
-       }
+       guint new_updates_counter;
+
+       new_updates_counter = _get_num_updates (self);
+       if (!gs_plugin_loader_get_allow_updates (self->plugin_loader) ||
+           self->state == GS_UPDATES_PAGE_STATE_FAILED)
+               new_updates_counter = 0;
 
-       /* update the tab style */
-       if (num_updates > 0 &&
-           gs_shell_get_mode (self->shell) != GS_SHELL_MODE_UPDATES)
-               gtk_style_context_add_class (gtk_widget_get_style_context (widget), "needs-attention");
-       else
-               gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "needs-attention");
+       if (new_updates_counter == self->updates_counter)
+               return;
+
+       self->updates_counter = new_updates_counter;
+       g_object_notify (G_OBJECT (self), "counter");
 }
 
 static void
@@ -430,7 +421,6 @@ gs_updates_page_get_updates_cb (GsPluginLoader *plugin_loader,
                                 GAsyncResult *res,
                                 GsUpdatesPage *self)
 {
-       GtkWidget *widget;
        g_autoptr(GError) error = NULL;
        g_autoptr(GsAppList) list = NULL;
 
@@ -445,9 +435,7 @@ gs_updates_page_get_updates_cb (GsPluginLoader *plugin_loader,
                gtk_label_set_label (GTK_LABEL (self->label_updates_failed),
                                     error->message);
                gs_updates_page_set_state (self, GS_UPDATES_PAGE_STATE_FAILED);
-               widget = GTK_WIDGET (gtk_builder_get_object (self->builder,
-                                                            "button_updates_counter"));
-               gtk_widget_hide (widget);
+               refresh_headerbar_updates_counter (self);
                return;
        }
 
@@ -1318,6 +1306,9 @@ gs_updates_page_get_property (GObject    *object,
        case PROP_TITLE:
                g_value_set_string (value, _("Updates"));
                break;
+       case PROP_COUNTER:
+               g_value_set_uint (value, self->updates_counter);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
@@ -1347,6 +1338,7 @@ gs_updates_page_set_property (GObject      *object,
                g_assert_not_reached ();
                break;
        case PROP_TITLE:
+       case PROP_COUNTER:
                /* Read only */
                g_assert_not_reached ();
                break;
@@ -1408,6 +1400,7 @@ gs_updates_page_class_init (GsUpdatesPageClass *klass)
        g_object_class_override_property (object_class, PROP_HSCROLL_POLICY, "hscroll-policy");
        g_object_class_override_property (object_class, PROP_VSCROLL_POLICY, "vscroll-policy");
        g_object_class_override_property (object_class, PROP_TITLE, "title");
+       g_object_class_override_property (object_class, PROP_COUNTER, "counter");
 
        gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-updates-page.ui");
 


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