summaryrefslogtreecommitdiffstats
path: root/src/gs-app-tile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gs-app-tile.c')
-rw-r--r--src/gs-app-tile.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/gs-app-tile.c b/src/gs-app-tile.c
new file mode 100644
index 0000000..50ee7c9
--- /dev/null
+++ b/src/gs-app-tile.c
@@ -0,0 +1,113 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2013 Matthias Clasen <mclasen@redhat.com>
+ * Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include "gs-app-tile.h"
+#include "gs-common.h"
+
+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 *self)
+{
+ GsAppTilePrivate *priv = gs_app_tile_get_instance_private (self);
+ g_return_val_if_fail (GS_IS_APP_TILE (self), NULL);
+ return priv->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;
+}
+
+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 *self, GsApp *app)
+{
+ 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 (self));
+ g_return_if_fail (!app || GS_IS_APP (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 && priv->app != 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);
+ }
+}
+
+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);
+
+ G_OBJECT_CLASS (gs_app_tile_parent_class)->finalize (object);
+}
+
+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 *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 *self = g_object_new (GS_TYPE_APP_TILE, NULL);
+ gs_app_tile_set_app (self, app);
+ return GTK_WIDGET (self);
+}