[gnome-software/wip/hughsie/GsAppTile] Make the objects that derive from GsAppTile simpler



commit 0546ef6c6136c18c93bbd051e5fbd40849aba230
Author: Richard Hughes <richard hughsie com>
Date:   Wed Jul 17 16:59:08 2019 +0100

    Make the objects that derive from GsAppTile simpler
    
    By storing the GsApp and the idle handle in the abstract object we can handle
    all the tricky signal handler logic correctly in one place rather than in three
    slightly-different ways.
    
    This fixes issues where the CSS properties get "out-of-sync" with reality.

 src/gs-app-tile.c     |  97 +++++++++++++++++++++-------
 src/gs-app-tile.h     |  12 ++--
 src/gs-feature-tile.c |  89 +++++---------------------
 src/gs-popular-tile.c |  94 ++++++---------------------
 src/gs-summary-tile.c | 173 +++++++++++++++++---------------------------------
 5 files changed, 172 insertions(+), 293 deletions(-)
---
diff --git a/src/gs-app-tile.c b/src/gs-app-tile.c
index 3401b5ba..0efd254d 100644
--- a/src/gs-app-tile.c
+++ b/src/gs-app-tile.c
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * Copyright (C) 2013 Matthias Clasen <mclasen redhat com>
+ * Copyright (C) 2019 Richard Hughes <richard hughsie com>
  *
  * SPDX-License-Identifier: GPL-2.0+
  */
@@ -10,50 +11,100 @@
 #include "gs-app-tile.h"
 #include "gs-common.h"
 
-G_DEFINE_ABSTRACT_TYPE (GsAppTile, gs_app_tile, GTK_TYPE_BUTTON)
+typedef struct {
+       GsApp                           *app;
+       guint                            app_state_changed_idle_id;
+} GsAppTilePrivate;
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GsAppTile, gs_app_tile, GTK_TYPE_BUTTON)
 
 GsApp *
-gs_app_tile_get_app (GsAppTile *tile)
+gs_app_tile_get_app (GsAppTile *self)
 {
-       GsAppTileClass *klass;
-
-       g_return_val_if_fail (GS_IS_APP_TILE (tile), NULL);
+       GsAppTilePrivate *priv = gs_app_tile_get_instance_private (self);
+       g_return_val_if_fail (GS_IS_APP_TILE (self), NULL);
+       return priv->app;
+}
 
-       klass = GS_APP_TILE_GET_CLASS (tile);
-       g_assert (klass->get_app);
+static gboolean
+gs_app_tile_state_changed_idle_cb (gpointer user_data)
+{
+       GsAppTile *self = GS_APP_TILE (user_data);
+       GsAppTileClass *klass = GS_APP_TILE_GET_CLASS (self);
+       GsAppTilePrivate *priv = gs_app_tile_get_instance_private (self);
+       priv->app_state_changed_idle_id = 0;
+       klass->refresh (self);
+       return G_SOURCE_REMOVE;
+}
 
-       return klass->get_app(tile);
+static void
+gs_app_tile_state_changed_cb (GsApp *app, GParamSpec *pspec, GsAppTile *self)
+{
+       GsAppTilePrivate *priv = gs_app_tile_get_instance_private (self);
+       g_clear_handle_id (&priv->app_state_changed_idle_id, g_source_remove);
+       priv->app_state_changed_idle_id = g_idle_add (gs_app_tile_state_changed_idle_cb, self);
 }
 
 void
-gs_app_tile_set_app (GsAppTile *tile, GsApp *app)
+gs_app_tile_set_app (GsAppTile *self, GsApp *app)
 {
-       GsAppTileClass *klass;
+       GsAppTileClass *klass = GS_APP_TILE_GET_CLASS (self);
+       GsAppTilePrivate *priv = gs_app_tile_get_instance_private (self);
 
-       g_return_if_fail (GS_IS_APP_TILE (tile));
+       g_return_if_fail (GS_IS_APP_TILE (self));
        g_return_if_fail (!app || GS_IS_APP (app));
 
-       klass = GS_APP_TILE_GET_CLASS (tile);
-       g_assert (klass->get_app);
+       /* cancel pending refresh */
+       g_clear_handle_id (&priv->app_state_changed_idle_id, g_source_remove);
+
+       /* disconnect old app */
+       if (priv->app != NULL)
+               g_signal_handlers_disconnect_by_func (priv->app, gs_app_tile_state_changed_cb, self);
+       g_set_object (&priv->app, app);
+
+       /* optional refresh */
+       if (klass->refresh != NULL) {
+               g_signal_connect (app, "notify::state",
+                                 G_CALLBACK (gs_app_tile_state_changed_cb), self);
+               g_signal_connect (app, "notify::name",
+                                 G_CALLBACK (gs_app_tile_state_changed_cb), self);
+               g_signal_connect (app, "notify::summary",
+                                 G_CALLBACK (gs_app_tile_state_changed_cb), self);
+               g_signal_connect (app, "notify::key-colors",
+                                 G_CALLBACK (gs_app_tile_state_changed_cb), self);
+               klass->refresh (self);
+       }
+}
 
-       klass->set_app(tile, app);
+static void
+gs_app_tile_finalize (GObject *object)
+{
+       GsAppTile *self = GS_APP_TILE (object);
+       GsAppTilePrivate *priv = gs_app_tile_get_instance_private (self);
+       if (priv->app != NULL)
+               g_signal_handlers_disconnect_by_func (priv->app, gs_app_tile_state_changed_cb, self);
+       g_clear_handle_id (&priv->app_state_changed_idle_id, g_source_remove);
+       g_clear_object (&priv->app);
 }
 
 void
 gs_app_tile_class_init (GsAppTileClass *klass)
-{}
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       object_class->finalize = gs_app_tile_finalize;
+}
 
 void
-gs_app_tile_init (GsAppTile *tile)
-{}
+gs_app_tile_init (GsAppTile *self)
+{
+       GsAppTilePrivate *priv = gs_app_tile_get_instance_private (self);
+       priv->app_state_changed_idle_id = 0;
+}
 
 GtkWidget *
 gs_app_tile_new (GsApp *app)
 {
-       GsAppTile *tile;
-
-       tile = g_object_new (GS_TYPE_APP_TILE, NULL);
-       gs_app_tile_set_app (tile, app);
-
-       return GTK_WIDGET (tile);
+       GsAppTile *self = g_object_new (GS_TYPE_APP_TILE, NULL);
+       gs_app_tile_set_app (self, app);
+       return GTK_WIDGET (self);
 }
diff --git a/src/gs-app-tile.h b/src/gs-app-tile.h
index 6469b5d6..554ab6dc 100644
--- a/src/gs-app-tile.h
+++ b/src/gs-app-tile.h
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * Copyright (C) 2013 Matthias Clasen <mclasen redhat com>
+ * Copyright (C) 2019 Richard Hughes <richard hughsie com>
  *
  * SPDX-License-Identifier: GPL-2.0+
  */
@@ -20,15 +21,12 @@ G_DECLARE_DERIVABLE_TYPE (GsAppTile, gs_app_tile, GS, APP_TILE, GtkButton)
 struct _GsAppTileClass
 {
        GtkButtonClass          parent_class;
-
-       void                    (*set_app)              (GsAppTile      *tile,
-                                                        GsApp          *app);
-        GsApp                  *(*get_app)             (GsAppTile      *tile);
+       void                     (*refresh)             (GsAppTile      *self);
 };
 
 GtkWidget      *gs_app_tile_new        (GsApp *app);
-GsApp          *gs_app_tile_get_app    (GsAppTile      *tile);
-void            gs_app_tile_set_app    (GsAppTile      *tile,
-                                        GsApp          *cat);
+GsApp          *gs_app_tile_get_app    (GsAppTile      *self);
+void            gs_app_tile_set_app    (GsAppTile      *self,
+                                        GsApp          *app);
 
 G_END_DECLS
diff --git a/src/gs-feature-tile.c b/src/gs-feature-tile.c
index b398946b..27b6f19a 100644
--- a/src/gs-feature-tile.c
+++ b/src/gs-feature-tile.c
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * Copyright (C) 2013 Matthias Clasen <mclasen redhat com>
+ * Copyright (C) 2019 Richard Hughes <richard hughsie com>
  *
  * SPDX-License-Identifier: GPL-2.0+
  */
@@ -17,39 +18,34 @@
 struct _GsFeatureTile
 {
        GsAppTile        parent_instance;
-
-       GsApp           *app;
        GtkWidget       *stack;
        GtkWidget       *title;
        GtkWidget       *subtitle;
-       guint            app_state_changed_id;
 };
 
 G_DEFINE_TYPE (GsFeatureTile, gs_feature_tile, GS_TYPE_APP_TILE)
 
-static GsApp *
-gs_feature_tile_get_app (GsAppTile *tile)
-{
-       return GS_FEATURE_TILE (tile)->app;
-}
-
-static gboolean
-app_state_changed_idle (gpointer user_data)
+static void
+gs_feature_tile_refresh (GsAppTile *self)
 {
-       GsFeatureTile *tile = GS_FEATURE_TILE (user_data);
+       GsFeatureTile *tile = GS_FEATURE_TILE (self);
+       GsApp *app = gs_app_tile_get_app (self);
        AtkObject *accessible;
        const gchar *markup;
        g_autofree gchar *name = NULL;
        g_autoptr(GsCss) css = NULL;
 
-       tile->app_state_changed_id = 0;
+       if (app == NULL)
+               return;
+
+       gtk_stack_set_visible_child_name (GTK_STACK (tile->stack), "content");
 
        /* update text */
-       gtk_label_set_label (GTK_LABEL (tile->title), gs_app_get_name (tile->app));
-       gtk_label_set_label (GTK_LABEL (tile->subtitle), gs_app_get_summary (tile->app));
+       gtk_label_set_label (GTK_LABEL (tile->title), gs_app_get_name (app));
+       gtk_label_set_label (GTK_LABEL (tile->subtitle), gs_app_get_summary (app));
 
        /* perhaps set custom css */
-       markup = gs_app_get_metadata_item (tile->app, "GnomeSoftware::FeatureTile-css");
+       markup = gs_app_get_metadata_item (app, "GnomeSoftware::FeatureTile-css");
        css = gs_css_new ();
        if (markup != NULL)
                gs_css_parse (css, markup, NULL);
@@ -62,74 +58,26 @@ app_state_changed_idle (gpointer user_data)
 
        accessible = gtk_widget_get_accessible (GTK_WIDGET (tile));
 
-       switch (gs_app_get_state (tile->app)) {
+       switch (gs_app_get_state (app)) {
        case AS_APP_STATE_INSTALLED:
        case AS_APP_STATE_REMOVING:
        case AS_APP_STATE_UPDATABLE:
        case AS_APP_STATE_UPDATABLE_LIVE:
                name = g_strdup_printf ("%s (%s)",
-                                       gs_app_get_name (tile->app),
+                                       gs_app_get_name (app),
                                        _("Installed"));
                break;
        case AS_APP_STATE_AVAILABLE:
        case AS_APP_STATE_INSTALLING:
        default:
-               name = g_strdup (gs_app_get_name (tile->app));
+               name = g_strdup (gs_app_get_name (app));
                break;
        }
 
        if (GTK_IS_ACCESSIBLE (accessible) && name != NULL) {
                atk_object_set_name (accessible, name);
-               atk_object_set_description (accessible, gs_app_get_summary (tile->app));
+               atk_object_set_description (accessible, gs_app_get_summary (app));
        }
-
-       return G_SOURCE_REMOVE;
-}
-
-static void
-app_state_changed (GsApp *app, GParamSpec *pspec, GsFeatureTile *tile)
-{
-       g_clear_handle_id (&tile->app_state_changed_id, g_source_remove);
-       tile->app_state_changed_id = g_idle_add (app_state_changed_idle, tile);
-}
-
-static void
-gs_feature_tile_set_app (GsAppTile *app_tile, GsApp *app)
-{
-       GsFeatureTile *tile = GS_FEATURE_TILE (app_tile);
-
-       g_return_if_fail (GS_IS_APP (app) || app == NULL);
-
-       if (tile->app != NULL)
-               g_signal_handlers_disconnect_by_func (tile->app, app_state_changed, tile);
-       g_clear_handle_id (&tile->app_state_changed_id, g_source_remove);
-
-       g_set_object (&tile->app, app);
-       if (app == NULL)
-               return;
-
-       gtk_stack_set_visible_child_name (GTK_STACK (tile->stack), "content");
-
-       g_signal_connect (tile->app, "notify::state",
-                         G_CALLBACK (app_state_changed), tile);
-       g_signal_connect (tile->app, "notify::name",
-                         G_CALLBACK (app_state_changed), tile);
-       g_signal_connect (tile->app, "notify::summary",
-                         G_CALLBACK (app_state_changed), tile);
-       app_state_changed (tile->app, NULL, tile);
-}
-
-static void
-gs_feature_tile_destroy (GtkWidget *widget)
-{
-       GsFeatureTile *tile = GS_FEATURE_TILE (widget);
-
-       if (tile->app != NULL)
-               g_signal_handlers_disconnect_by_func (tile->app, app_state_changed, tile);
-       g_clear_handle_id (&tile->app_state_changed_id, g_source_remove);
-       g_clear_object (&tile->app);
-
-       GTK_WIDGET_CLASS (gs_feature_tile_parent_class)->destroy (widget);
 }
 
 static void
@@ -145,10 +93,7 @@ gs_feature_tile_class_init (GsFeatureTileClass *klass)
        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
        GsAppTileClass *app_tile_class = GS_APP_TILE_CLASS (klass);
 
-       widget_class->destroy = gs_feature_tile_destroy;
-
-       app_tile_class->set_app = gs_feature_tile_set_app;
-       app_tile_class->get_app = gs_feature_tile_get_app;
+       app_tile_class->refresh = gs_feature_tile_refresh;
 
        gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-feature-tile.ui");
 
diff --git a/src/gs-popular-tile.c b/src/gs-popular-tile.c
index 04dc3ac4..0ad7c65e 100644
--- a/src/gs-popular-tile.c
+++ b/src/gs-popular-tile.c
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * Copyright (C) 2013 Matthias Clasen <mclasen redhat com>
+ * Copyright (C) 2019 Richard Hughes <richard hughsie com>
  *
  * SPDX-License-Identifier: GPL-2.0+
  */
@@ -17,37 +18,31 @@
 struct _GsPopularTile
 {
        GsAppTile        parent_instance;
-
-       GsApp           *app;
        GtkWidget       *label;
        GtkWidget       *image;
        GtkWidget       *eventbox;
        GtkWidget       *stack;
        GtkWidget       *stars;
-       guint            app_state_changed_id;
 };
 
 G_DEFINE_TYPE (GsPopularTile, gs_popular_tile, GS_TYPE_APP_TILE)
 
-static GsApp *
-gs_popular_tile_get_app (GsAppTile *tile)
-{
-       return GS_POPULAR_TILE (tile)->app;
-}
-
-static gboolean
-app_state_changed_idle (gpointer user_data)
+static void
+gs_popular_tile_refresh (GsAppTile *self)
 {
-       GsPopularTile *tile = GS_POPULAR_TILE (user_data);
+       GsPopularTile *tile = GS_POPULAR_TILE (self);
+       GsApp *app = gs_app_tile_get_app (self);
        AtkObject *accessible;
        gboolean installed;
        g_autofree gchar *name = NULL;
+       const gchar *css;
 
-       tile->app_state_changed_id = 0;
+       if (app == NULL)
+               return;
 
        accessible = gtk_widget_get_accessible (GTK_WIDGET (tile));
 
-       switch (gs_app_get_state (tile->app)) {
+       switch (gs_app_get_state (app)) {
        case AS_APP_STATE_INSTALLED:
        case AS_APP_STATE_REMOVING:
        case AS_APP_STATE_UPDATABLE:
@@ -55,13 +50,13 @@ app_state_changed_idle (gpointer user_data)
                installed = TRUE;
                /* TRANSLATORS: this refers to an app (by name) that is installed */
                name = g_strdup_printf (_("%s (Installed)"),
-                                       gs_app_get_name (tile->app));
+                                       gs_app_get_name (app));
                break;
        case AS_APP_STATE_AVAILABLE:
        case AS_APP_STATE_INSTALLING:
        default:
                installed = FALSE;
-               name = g_strdup (gs_app_get_name (tile->app));
+               name = g_strdup (gs_app_get_name (app));
                break;
        }
 
@@ -69,58 +64,24 @@ app_state_changed_idle (gpointer user_data)
 
        if (GTK_IS_ACCESSIBLE (accessible)) {
                atk_object_set_name (accessible, name);
-               atk_object_set_description (accessible, gs_app_get_summary (tile->app));
+               atk_object_set_description (accessible, gs_app_get_summary (app));
        }
 
-       return G_SOURCE_REMOVE;
-}
-
-static void
-app_state_changed (GsApp *app, GParamSpec *pspec, GsPopularTile *tile)
-{
-       g_clear_handle_id (&tile->app_state_changed_id, g_source_remove);
-       tile->app_state_changed_id = g_idle_add (app_state_changed_idle, tile);
-}
-
-static void
-gs_popular_tile_set_app (GsAppTile *app_tile, GsApp *app)
-{
-       GsPopularTile *tile = GS_POPULAR_TILE (app_tile);
-       const gchar *css;
-
-       g_return_if_fail (GS_IS_APP (app) || app == NULL);
-
-       if (tile->app != NULL)
-               g_signal_handlers_disconnect_by_func (tile->app, app_state_changed, tile);
-       g_clear_handle_id (&tile->app_state_changed_id, g_source_remove);
-
-       g_set_object (&tile->app, app);
-       if (!app)
-               return;
-
-       if (gs_app_get_rating (tile->app) >= 0) {
+       if (gs_app_get_rating (app) >= 0) {
                gtk_widget_set_sensitive (tile->stars, TRUE);
                gs_star_widget_set_rating (GS_STAR_WIDGET (tile->stars),
-                                          gs_app_get_rating (tile->app));
+                                          gs_app_get_rating (app));
        } else {
                gtk_widget_set_sensitive (tile->stars, FALSE);
        }
        gtk_stack_set_visible_child_name (GTK_STACK (tile->stack), "content");
 
-       g_signal_connect (tile->app, "notify::state",
-                         G_CALLBACK (app_state_changed), tile);
-       g_signal_connect (tile->app, "notify::name",
-                         G_CALLBACK (app_state_changed), tile);
-       g_signal_connect (tile->app, "notify::summary",
-                         G_CALLBACK (app_state_changed), tile);
-       app_state_changed (tile->app, NULL, tile);
-
        /* perhaps set custom css */
        css = gs_app_get_metadata_item (app, "GnomeSoftware::PopularTile-css");
        gs_utils_widget_set_css (GTK_WIDGET (tile), css);
 
-       if (gs_app_get_pixbuf (tile->app) != NULL) {
-               gs_image_set_from_pixbuf (GTK_IMAGE (tile->image), gs_app_get_pixbuf (tile->app));
+       if (gs_app_get_pixbuf (app) != NULL) {
+               gs_image_set_from_pixbuf (GTK_IMAGE (tile->image), gs_app_get_pixbuf (app));
        } else {
                gtk_image_set_from_icon_name (GTK_IMAGE (tile->image),
                                              "application-x-executable",
@@ -130,19 +91,6 @@ gs_popular_tile_set_app (GsAppTile *app_tile, GsApp *app)
        gtk_label_set_label (GTK_LABEL (tile->label), gs_app_get_name (app));
 }
 
-static void
-gs_popular_tile_destroy (GtkWidget *widget)
-{
-       GsPopularTile *tile = GS_POPULAR_TILE (widget);
-
-       if (tile->app != NULL)
-               g_signal_handlers_disconnect_by_func (tile->app, app_state_changed, tile);
-       g_clear_handle_id (&tile->app_state_changed_id, g_source_remove);
-       g_clear_object (&tile->app);
-
-       GTK_WIDGET_CLASS (gs_popular_tile_parent_class)->destroy (widget);
-}
-
 static void
 gs_popular_tile_init (GsPopularTile *tile)
 {
@@ -157,10 +105,7 @@ gs_popular_tile_class_init (GsPopularTileClass *klass)
        GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
        GsAppTileClass *app_tile_class = GS_APP_TILE_CLASS (klass);
 
-       widget_class->destroy = gs_popular_tile_destroy;
-
-       app_tile_class->set_app = gs_popular_tile_set_app;
-       app_tile_class->get_app = gs_popular_tile_get_app;
+       app_tile_class->refresh = gs_popular_tile_refresh;
 
        gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-popular-tile.ui");
 
@@ -174,11 +119,8 @@ gs_popular_tile_class_init (GsPopularTileClass *klass)
 GtkWidget *
 gs_popular_tile_new (GsApp *app)
 {
-       GsPopularTile *tile;
-
-       tile = g_object_new (GS_TYPE_POPULAR_TILE, NULL);
+       GsPopularTile *tile = g_object_new (GS_TYPE_POPULAR_TILE, NULL);
        if (app != NULL)
                gs_app_tile_set_app (GS_APP_TILE (tile), app);
-
        return GTK_WIDGET (tile);
 }
diff --git a/src/gs-summary-tile.c b/src/gs-summary-tile.c
index d568e218..3fe57277 100644
--- a/src/gs-summary-tile.c
+++ b/src/gs-summary-tile.c
@@ -1,6 +1,7 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * Copyright (C) 2013 Matthias Clasen <mclasen redhat com>
+ * Copyright (C) 2019 Richard Hughes <richard hughsie com>
  *
  * SPDX-License-Identifier: GPL-2.0+
  */
@@ -15,14 +16,11 @@
 struct _GsSummaryTile
 {
        GsAppTile        parent_instance;
-
-       GsApp           *app;
        GtkWidget       *image;
        GtkWidget       *name;
        GtkWidget       *summary;
        GtkWidget       *eventbox;
        GtkWidget       *stack;
-       guint            app_state_changed_id;
        gint             preferred_width;
 };
 
@@ -33,98 +31,42 @@ enum {
        PROP_PREFERRED_WIDTH
 };
 
-static GsApp *
-gs_summary_tile_get_app (GsAppTile *tile)
-{
-       return GS_SUMMARY_TILE (tile)->app;
-}
-
-static gboolean
-app_state_changed_idle (gpointer user_data)
+static void
+gs_summary_tile_refresh (GsAppTile *self)
 {
-       GsSummaryTile *tile = GS_SUMMARY_TILE (user_data);
+       GsSummaryTile *tile = GS_SUMMARY_TILE (self);
+       GsApp *app = gs_app_tile_get_app (self);
        AtkObject *accessible;
+       GtkStyleContext *context;
+       const GdkPixbuf *pixbuf;
        gboolean installed;
        g_autofree gchar *name = NULL;
+       g_autofree gchar *summary = NULL;
+       const gchar *css;
 
-       tile->app_state_changed_id = 0;
+       if (app == NULL)
+               return;
 
-       accessible = gtk_widget_get_accessible (GTK_WIDGET (tile));
+       gtk_image_set_pixel_size (GTK_IMAGE (tile->image), 64);
+       gtk_stack_set_visible_child_name (GTK_STACK (tile->stack), "content");
 
-       switch (gs_app_get_state (tile->app)) {
-       case AS_APP_STATE_INSTALLED:
-       case AS_APP_STATE_UPDATABLE:
-       case AS_APP_STATE_UPDATABLE_LIVE:
-               installed = TRUE;
-               name = g_strdup_printf (_("%s (Installed)"),
-                                       gs_app_get_name (tile->app));
-               break;
-       case AS_APP_STATE_INSTALLING:
-               installed = FALSE;
-               name = g_strdup_printf (_("%s (Installing)"),
-                                       gs_app_get_name (tile->app));
-               break;
-       case AS_APP_STATE_REMOVING:
-               installed = TRUE;
-               name = g_strdup_printf (_("%s (Removing)"),
-                                       gs_app_get_name (tile->app));
+       /* set name */
+       gtk_label_set_label (GTK_LABEL (tile->name), gs_app_get_name (app));
+
+       /* some kinds have boring summaries */
+       switch (gs_app_get_kind (app)) {
+       case AS_APP_KIND_SHELL_EXTENSION:
+               summary = g_strdup (gs_app_get_description (app));
+               if (summary != NULL)
+                       g_strdelimit (summary, "\n\t", ' ');
                break;
-       case AS_APP_STATE_QUEUED_FOR_INSTALL:
-       case AS_APP_STATE_AVAILABLE:
        default:
-               installed = FALSE;
-               name = g_strdup (gs_app_get_name (tile->app));
+               summary = g_strdup (gs_app_get_summary (app));
                break;
        }
 
-       gtk_widget_set_visible (tile->eventbox, installed);
-
-       if (GTK_IS_ACCESSIBLE (accessible) && name != NULL) {
-               atk_object_set_name (accessible, name);
-               atk_object_set_description (accessible, gs_app_get_summary (tile->app));
-       }
-
-       return G_SOURCE_REMOVE;
-}
-
-static void
-app_state_changed (GsApp *app, GParamSpec *pspec, GsSummaryTile *tile)
-{
-       g_clear_handle_id (&tile->app_state_changed_id, g_source_remove);
-       tile->app_state_changed_id = g_idle_add (app_state_changed_idle, tile);
-}
-
-static void
-gs_summary_tile_set_app (GsAppTile *app_tile, GsApp *app)
-{
-       GtkStyleContext *context;
-       const GdkPixbuf *pixbuf;
-       GsSummaryTile *tile = GS_SUMMARY_TILE (app_tile);
-       const gchar *css;
-       g_autofree gchar *text = NULL;
-
-       g_return_if_fail (GS_IS_APP (app) || app == NULL);
-
-       gtk_image_clear (GTK_IMAGE (tile->image));
-       gtk_image_set_pixel_size (GTK_IMAGE (tile->image), 64);
-
-       if (tile->app != NULL)
-               g_signal_handlers_disconnect_by_func (tile->app, app_state_changed, tile);
-       g_clear_handle_id (&tile->app_state_changed_id, g_source_remove);
-
-       g_set_object (&tile->app, app);
-       if (!app)
-               return;
-
-       gtk_stack_set_visible_child_name (GTK_STACK (tile->stack), "content");
-
-       g_signal_connect (tile->app, "notify::state",
-                         G_CALLBACK (app_state_changed), tile);
-       g_signal_connect (tile->app, "notify::name",
-                         G_CALLBACK (app_state_changed), tile);
-       g_signal_connect (tile->app, "notify::summary",
-                         G_CALLBACK (app_state_changed), tile);
-       app_state_changed (tile->app, NULL, tile);
+       gtk_label_set_label (GTK_LABEL (tile->summary), summary);
+       gtk_widget_set_visible (tile->summary, summary && summary[0]);
 
        pixbuf = gs_app_get_pixbuf (app);
        if (pixbuf != NULL) {
@@ -134,10 +76,8 @@ gs_summary_tile_set_app (GsAppTile *app_tile, GsApp *app)
                                              "application-x-executable",
                                              GTK_ICON_SIZE_DIALOG);
        }
-       gtk_label_set_label (GTK_LABEL (tile->name), gs_app_get_name (app));
-
        context = gtk_widget_get_style_context (tile->image);
-       if (gs_app_get_use_drop_shadow (tile->app))
+       if (gs_app_get_use_drop_shadow (app))
                gtk_style_context_add_class (context, "icon-dropshadow");
        else
                gtk_style_context_remove_class (context, "icon-dropshadow");
@@ -146,33 +86,40 @@ gs_summary_tile_set_app (GsAppTile *app_tile, GsApp *app)
        css = gs_app_get_metadata_item (app, "GnomeSoftware::AppTile-css");
        gs_utils_widget_set_css (GTK_WIDGET (tile), css);
 
-       /* some kinds have boring summaries */
-       switch (gs_app_get_kind (app)) {
-       case AS_APP_KIND_SHELL_EXTENSION:
-               text = g_strdup (gs_app_get_description (app));
-               if (text != NULL)
-                       g_strdelimit (text, "\n\t", ' ');
+       accessible = gtk_widget_get_accessible (GTK_WIDGET (tile));
+
+       switch (gs_app_get_state (app)) {
+       case AS_APP_STATE_INSTALLED:
+       case AS_APP_STATE_UPDATABLE:
+       case AS_APP_STATE_UPDATABLE_LIVE:
+               installed = TRUE;
+               name = g_strdup_printf (_("%s (Installed)"),
+                                       gs_app_get_name (app));
+               break;
+       case AS_APP_STATE_INSTALLING:
+               installed = FALSE;
+               name = g_strdup_printf (_("%s (Installing)"),
+                                       gs_app_get_name (app));
+               break;
+       case AS_APP_STATE_REMOVING:
+               installed = TRUE;
+               name = g_strdup_printf (_("%s (Removing)"),
+                                       gs_app_get_name (app));
                break;
+       case AS_APP_STATE_QUEUED_FOR_INSTALL:
+       case AS_APP_STATE_AVAILABLE:
        default:
-               text = g_strdup (gs_app_get_summary (app));
+               installed = FALSE;
+               name = g_strdup (gs_app_get_name (app));
                break;
        }
 
-       gtk_label_set_label (GTK_LABEL (tile->summary), text);
-       gtk_widget_set_visible (tile->summary, text && text[0]);
-}
-
-static void
-gs_summary_tile_destroy (GtkWidget *widget)
-{
-       GsSummaryTile *tile = GS_SUMMARY_TILE (widget);
-
-       if (tile->app != NULL)
-               g_signal_handlers_disconnect_by_func (tile->app, app_state_changed, tile);
-       g_clear_handle_id (&tile->app_state_changed_id, g_source_remove);
-       g_clear_object (&tile->app);
+       gtk_widget_set_visible (tile->eventbox, installed);
 
-       GTK_WIDGET_CLASS (gs_summary_tile_parent_class)->destroy (widget);
+       if (GTK_IS_ACCESSIBLE (accessible) && name != NULL) {
+               atk_object_set_name (accessible, name);
+               atk_object_set_description (accessible, gs_app_get_summary (app));
+       }
 }
 
 static void
@@ -180,6 +127,7 @@ gs_summary_tile_init (GsSummaryTile *tile)
 {
        gtk_widget_set_has_window (GTK_WIDGET (tile), FALSE);
        tile->preferred_width = -1;
+//     gtk_image_clear (GTK_IMAGE (tile->image));
        gtk_widget_init_template (GTK_WIDGET (tile));
 }
 
@@ -251,11 +199,9 @@ gs_summary_tile_class_init (GsSummaryTileClass *klass)
        object_class->get_property = gs_summary_tile_get_property;
        object_class->set_property = gs_summary_tile_set_property;
 
-       widget_class->destroy = gs_summary_tile_destroy;
        widget_class->get_preferred_width = gs_app_get_preferred_width;
 
-       tile_class->set_app = gs_summary_tile_set_app;
-       tile_class->get_app = gs_summary_tile_get_app;
+       tile_class->refresh = gs_summary_tile_refresh;
 
        /**
         * GsAppTile:preferred-width:
@@ -293,10 +239,7 @@ gs_summary_tile_class_init (GsSummaryTileClass *klass)
 GtkWidget *
 gs_summary_tile_new (GsApp *cat)
 {
-       GsAppTile *tile;
-
-       tile = g_object_new (GS_TYPE_SUMMARY_TILE, NULL);
-       gs_summary_tile_set_app (tile, cat);
-
+       GsAppTile *tile = g_object_new (GS_TYPE_SUMMARY_TILE, NULL);
+       gs_app_tile_set_app (tile, cat);
        return GTK_WIDGET (tile);
 }


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