]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-roster-group.c
UOA: Do not segfault when "Done" or "Cancel" button clicked but widget is not ready yet
[empathy.git] / libempathy-gtk / empathy-roster-group.c
1 #include "config.h"
2
3 #include "empathy-roster-group.h"
4
5 #include <telepathy-glib/telepathy-glib.h>
6
7 G_DEFINE_TYPE (EmpathyRosterGroup, empathy_roster_group, GTK_TYPE_EXPANDER)
8
9 enum
10 {
11   PROP_NAME = 1,
12   PROP_ICON,
13   N_PROPS
14 };
15
16 /*
17 enum
18 {
19   LAST_SIGNAL
20 };
21
22 static guint signals[LAST_SIGNAL];
23 */
24
25 struct _EmpathyRosterGroupPriv
26 {
27   gchar *name;
28   gchar *icon_name;
29
30   /* Widgets associated with this group. EmpathyRosterGroup is not responsible
31    * of packing/displaying these widgets. This hash table is a just a set
32    * to keep track of them. */
33   GHashTable *widgets;
34 };
35
36 static void
37 empathy_roster_group_get_property (GObject *object,
38     guint property_id,
39     GValue *value,
40     GParamSpec *pspec)
41 {
42   EmpathyRosterGroup *self = EMPATHY_ROSTER_GROUP (object);
43
44   switch (property_id)
45     {
46       case PROP_NAME:
47         g_value_set_string (value, self->priv->name);
48         break;
49       case PROP_ICON:
50         g_value_set_string (value, self->priv->icon_name);
51         break;
52       default:
53         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
54         break;
55     }
56 }
57
58 static void
59 empathy_roster_group_set_property (GObject *object,
60     guint property_id,
61     const GValue *value,
62     GParamSpec *pspec)
63 {
64   EmpathyRosterGroup *self = EMPATHY_ROSTER_GROUP (object);
65
66   switch (property_id)
67     {
68       case PROP_NAME:
69         g_assert (self->priv->name == NULL); /* construct-only */
70         self->priv->name = g_value_dup_string (value);
71         break;
72       case PROP_ICON:
73         g_assert (self->priv->icon_name == NULL); /* construct-only */
74         self->priv->icon_name = g_value_dup_string (value);
75         break;
76       default:
77         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
78         break;
79     }
80 }
81
82 static void
83 empathy_roster_group_constructed (GObject *object)
84 {
85   EmpathyRosterGroup *self = EMPATHY_ROSTER_GROUP (object);
86   void (*chain_up) (GObject *) =
87       ((GObjectClass *) empathy_roster_group_parent_class)->constructed;
88   gchar *tmp;
89   GtkWidget *box, *label;
90
91   if (chain_up != NULL)
92     chain_up (object);
93
94   g_assert (self->priv->name != NULL);
95
96   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
97
98   /* Icon, if any */
99   if (!tp_str_empty (self->priv->icon_name))
100     {
101       GtkWidget *icon;
102
103       icon = gtk_image_new_from_icon_name (self->priv->icon_name,
104           GTK_ICON_SIZE_MENU);
105
106       if (icon != NULL)
107         gtk_box_pack_start (GTK_BOX (box), icon, FALSE, FALSE, 0);
108     }
109
110   /* Label */
111   tmp = g_strdup_printf ("<b>%s</b>", self->priv->name);
112   label = gtk_label_new (tmp);
113   g_free (tmp);
114
115   gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
116   gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 0);
117
118   gtk_widget_show_all (box);
119
120   gtk_expander_set_label_widget (GTK_EXPANDER (self), box);
121 }
122
123 static void
124 empathy_roster_group_dispose (GObject *object)
125 {
126   EmpathyRosterGroup *self = EMPATHY_ROSTER_GROUP (object);
127   void (*chain_up) (GObject *) =
128       ((GObjectClass *) empathy_roster_group_parent_class)->dispose;
129
130   tp_clear_pointer (&self->priv->widgets, g_hash_table_unref);
131
132   if (chain_up != NULL)
133     chain_up (object);
134 }
135
136 static void
137 empathy_roster_group_finalize (GObject *object)
138 {
139   EmpathyRosterGroup *self = EMPATHY_ROSTER_GROUP (object);
140   void (*chain_up) (GObject *) =
141       ((GObjectClass *) empathy_roster_group_parent_class)->finalize;
142
143   g_free (self->priv->name);
144   g_free (self->priv->icon_name);
145
146   if (chain_up != NULL)
147     chain_up (object);
148 }
149
150 static void
151 empathy_roster_group_class_init (
152     EmpathyRosterGroupClass *klass)
153 {
154   GObjectClass *oclass = G_OBJECT_CLASS (klass);
155   GParamSpec *spec;
156
157   oclass->get_property = empathy_roster_group_get_property;
158   oclass->set_property = empathy_roster_group_set_property;
159   oclass->constructed = empathy_roster_group_constructed;
160   oclass->dispose = empathy_roster_group_dispose;
161   oclass->finalize = empathy_roster_group_finalize;
162
163   spec = g_param_spec_string ("name", "Name",
164       "Group name",
165       NULL,
166       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
167   g_object_class_install_property (oclass, PROP_NAME, spec);
168
169   spec = g_param_spec_string ("icon", "Icon",
170       "Icon name",
171       NULL,
172       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
173   g_object_class_install_property (oclass, PROP_ICON, spec);
174
175   g_type_class_add_private (klass, sizeof (EmpathyRosterGroupPriv));
176 }
177
178 static void
179 empathy_roster_group_init (EmpathyRosterGroup *self)
180 {
181   self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
182       EMPATHY_TYPE_ROSTER_GROUP, EmpathyRosterGroupPriv);
183
184   self->priv->widgets = g_hash_table_new (NULL, NULL);
185 }
186
187 GtkWidget *
188 empathy_roster_group_new (const gchar *name,
189     const gchar *icon)
190 {
191   return g_object_new (EMPATHY_TYPE_ROSTER_GROUP,
192       "name", name,
193       "icon", icon,
194       "use-markup", TRUE,
195       "expanded", TRUE,
196       NULL);
197 }
198
199 const gchar *
200 empathy_roster_group_get_name (EmpathyRosterGroup *self)
201 {
202   return self->priv->name;
203 }
204
205 guint
206 empathy_roster_group_add_widget (EmpathyRosterGroup *self,
207     GtkWidget *widget)
208 {
209   g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
210
211   g_hash_table_add (self->priv->widgets, widget);
212
213   return empathy_roster_group_get_widgets_count (self);
214 }
215
216 guint
217 empathy_roster_group_remove_widget (EmpathyRosterGroup *self,
218     GtkWidget *widget)
219 {
220   g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
221
222   g_hash_table_remove (self->priv->widgets, widget);
223
224   return empathy_roster_group_get_widgets_count (self);
225 }
226
227 guint
228 empathy_roster_group_get_widgets_count (EmpathyRosterGroup *self)
229 {
230   return g_hash_table_size (self->priv->widgets);
231 }
232
233 GList *
234 empathy_roster_group_get_widgets (EmpathyRosterGroup *self)
235 {
236   return g_hash_table_get_keys (self->priv->widgets);
237 }