summaryrefslogtreecommitdiffstats
path: root/src/gs-app-tile.c
blob: 50ee7c9d7bcf26f38932321d16afe8d77540531a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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);
}