]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-contact-selector.c
tidy
[empathy.git] / libempathy-gtk / empathy-contact-selector.c
1 /*
2 *  Copyright (C) 2007 Marco Barisione <marco@barisione.org>
3 *  Copyright (C) 2008 Collabora Ltd.
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 *
19 *  Authors: Marco Barisione <marco@barisione.org>
20 *           Elliot Fairweather <elliot.fairweather@collabora.co.uk>
21 */
22
23 #include "config.h"
24
25 #include <glib/gi18n.h>
26 #include <gtk/gtk.h>
27
28 #include <libempathy/empathy-contact.h>
29 #include <libempathy-gtk/empathy-contact-list-store.h>
30 #include "empathy-contact-selector.h"
31
32 G_DEFINE_TYPE (EmpathyContactSelector, empathy_contact_selector,
33     GTK_TYPE_COMBO_BOX)
34
35 #define GET_PRIV(object) (G_TYPE_INSTANCE_GET_PRIVATE \
36     ((object), EMPATHY_TYPE_CONTACT_SELECTOR, EmpathyContactSelectorPriv))
37
38 enum
39 {
40   PROP_0,
41   PROP_STORE
42 };
43
44 typedef struct _EmpathyContactSelectorPriv EmpathyContactSelectorPriv;
45
46 struct _EmpathyContactSelectorPriv
47 {
48   EmpathyContactListStore *store;
49   gboolean is_blank_set;
50 };
51
52 static void changed_cb (GtkComboBox *widget, gpointer data);
53
54
55 EmpathyContact *
56 empathy_contact_selector_get_selected (EmpathyContactSelector *selector)
57 {
58   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
59   EmpathyContact *contact = NULL;
60   GtkTreeIter iter;
61
62   if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (selector), &iter))
63     return NULL;
64
65   gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
66       EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact, -1);
67
68   return contact;
69 }
70
71
72 static guint
73 get_number_online_contacts (GtkTreeStore *store)
74 {
75   GtkTreePath *path;
76   GtkTreeIter tmp_iter;
77   gboolean is_online;
78   guint number_online_contacts = 0;
79
80   path = gtk_tree_path_new_first ();
81
82   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &tmp_iter, path))
83     {
84       do
85         {
86           gtk_tree_model_get (GTK_TREE_MODEL (store),
87               &tmp_iter, EMPATHY_CONTACT_LIST_STORE_COL_IS_ONLINE,
88               &is_online, -1);
89           if (is_online)
90             number_online_contacts++;
91         } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &tmp_iter));
92     }
93
94   gtk_tree_path_free (path);
95
96   return number_online_contacts;
97 }
98
99
100 static gboolean
101 get_iter_for_blank_contact (GtkTreeStore *store,
102                             GtkTreeIter *blank_iter)
103 {
104   GtkTreePath *path;
105   GtkTreeIter tmp_iter;
106   EmpathyContact *tmp_contact;
107   gboolean is_present = FALSE;
108
109   path = gtk_tree_path_new_first ();
110
111   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &tmp_iter, path))
112     {
113       do
114         {
115           gtk_tree_model_get (GTK_TREE_MODEL (store),
116               &tmp_iter, EMPATHY_CONTACT_LIST_STORE_COL_CONTACT,
117               &tmp_contact, -1);
118           if (tmp_contact == NULL)
119             {
120               *blank_iter = tmp_iter;
121               is_present = TRUE;
122               break;
123             }
124         } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &tmp_iter));
125     }
126
127   gtk_tree_path_free (path);
128
129   return is_present;
130 }
131
132
133 static void
134 set_blank_contact (EmpathyContactSelector *selector)
135 {
136   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
137   GtkTreeIter blank_iter;
138
139   gtk_tree_store_insert (GTK_TREE_STORE (priv->store), &blank_iter, NULL, 0);
140   gtk_tree_store_set (GTK_TREE_STORE (priv->store), &blank_iter,
141       EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, NULL,
142       EMPATHY_CONTACT_LIST_STORE_COL_NAME, ("Select a contact"),
143       EMPATHY_CONTACT_LIST_STORE_COL_IS_ONLINE, FALSE, -1);
144   g_signal_handlers_block_by_func(selector, changed_cb, NULL);
145   gtk_combo_box_set_active_iter (GTK_COMBO_BOX (selector), &blank_iter);
146   g_signal_handlers_unblock_by_func(selector, changed_cb, NULL);
147   priv->is_blank_set = TRUE;
148 }
149
150
151 static void
152 unset_blank_contact (EmpathyContactSelector *selector)
153 {
154   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
155   GtkTreeIter blank_iter;
156
157   if (get_iter_for_blank_contact (GTK_TREE_STORE (priv->store), &blank_iter))
158     {
159       gtk_tree_store_remove (GTK_TREE_STORE (priv->store), &blank_iter);
160       priv->is_blank_set = FALSE;
161     }
162 }
163
164
165 static void
166 manage_sensitivity (EmpathyContactSelector *selector)
167 {
168   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
169   guint number_online_contacts =
170       get_number_online_contacts (GTK_TREE_STORE (priv->store));
171
172   if (number_online_contacts == 0 && priv->is_blank_set)
173       gtk_widget_set_sensitive (GTK_WIDGET (selector), FALSE);
174   else if (number_online_contacts)
175       gtk_widget_set_sensitive (GTK_WIDGET (selector), TRUE);
176   else
177       gtk_widget_set_sensitive (GTK_WIDGET (selector), FALSE);
178 }
179
180
181 static void
182 manage_blank_contact (EmpathyContactSelector *selector)
183 {
184   gboolean is_popup_shown;
185
186   g_object_get (selector, "popup-shown", &is_popup_shown, NULL);
187
188   if (is_popup_shown)
189     {
190       unset_blank_contact (selector);
191     }
192   else
193     {
194       if (gtk_combo_box_get_active (GTK_COMBO_BOX (selector)) == -1)
195         {
196           set_blank_contact (selector);
197         }
198       else
199         {
200           unset_blank_contact (selector);
201         }
202     }
203
204     manage_sensitivity (selector);
205 }
206
207
208 static void
209 notify_popup_shown_cb (GtkComboBox *widget,
210                        GParamSpec *property,
211                        gpointer data)
212 {
213   EmpathyContactSelector *selector = EMPATHY_CONTACT_SELECTOR (widget);
214
215   manage_blank_contact (selector);
216 }
217
218
219 static void
220 changed_cb (GtkComboBox *widget,
221             gpointer data)
222 {
223   EmpathyContactSelector *selector = EMPATHY_CONTACT_SELECTOR (widget);
224
225   manage_blank_contact (selector);
226 }
227
228
229 static void
230 empathy_store_row_changed_cb (EmpathyContactListStore *empathy_store,
231                               GtkTreePath *empathy_path,
232                               GtkTreeIter *empathy_iter,
233                               gpointer data)
234 {
235   EmpathyContactSelector *selector = EMPATHY_CONTACT_SELECTOR (data);
236
237   manage_sensitivity (selector);
238 }
239
240
241 static GObject *
242 empathy_contact_selector_constructor (GType type,
243                                       guint n_construct_params,
244                                       GObjectConstructParam *construct_params)
245 {
246   GObject *object =
247       G_OBJECT_CLASS (empathy_contact_selector_parent_class)->constructor (type,
248       n_construct_params, construct_params);
249   EmpathyContactSelector *contact_selector = EMPATHY_CONTACT_SELECTOR (object);
250   EmpathyContactSelectorPriv *priv = GET_PRIV (contact_selector);
251   GtkCellRenderer *renderer;
252
253   g_object_set (priv->store, "is-compact", TRUE, "show-avatars", FALSE,
254       "show-offline", FALSE, "show-groups", FALSE,
255       "sort-criterium", EMPATHY_CONTACT_LIST_STORE_SORT_NAME, NULL);
256
257   g_signal_connect (priv->store, "row-changed",
258       G_CALLBACK (empathy_store_row_changed_cb), (gpointer) contact_selector);
259   g_signal_connect (GTK_COMBO_BOX (contact_selector), "changed",
260       G_CALLBACK (changed_cb), NULL);
261   g_signal_connect (GTK_COMBO_BOX (contact_selector), "notify::popup-shown",
262       G_CALLBACK (notify_popup_shown_cb), NULL);
263
264   gtk_combo_box_set_model (GTK_COMBO_BOX (contact_selector),
265       GTK_TREE_MODEL (priv->store));
266   gtk_widget_set_sensitive (GTK_WIDGET (contact_selector), FALSE);
267
268   renderer = gtk_cell_renderer_pixbuf_new ();
269   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (contact_selector),
270       renderer, FALSE);
271   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (contact_selector), renderer,
272       "icon-name", EMPATHY_CONTACT_LIST_STORE_COL_ICON_STATUS, NULL);
273
274   renderer = gtk_cell_renderer_text_new ();
275   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (contact_selector),
276       renderer, TRUE);
277   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (contact_selector), renderer,
278       "text", EMPATHY_CONTACT_LIST_STORE_COL_NAME, NULL);
279
280   manage_blank_contact (contact_selector);
281   manage_sensitivity (contact_selector);
282
283   object = G_OBJECT (contact_selector);
284   return object;
285 }
286
287
288 static void
289 empathy_contact_selector_init (EmpathyContactSelector *empathy_contact_selector)
290 {
291 }
292
293
294 static void
295 empathy_contact_selector_set_property (GObject *object,
296                                        guint prop_id,
297                                        const GValue *value,
298                                        GParamSpec *pspec)
299 {
300   EmpathyContactSelector *contact_selector = EMPATHY_CONTACT_SELECTOR (object);
301   EmpathyContactSelectorPriv *priv = GET_PRIV (contact_selector);
302
303   switch (prop_id)
304     {
305       case PROP_STORE:
306         priv->store = g_value_dup_object (value);
307         break;
308       default:
309         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
310         break;
311     }
312 }
313
314
315 static void
316 empathy_contact_selector_get_property (GObject *object,
317                                        guint prop_id,
318                                        GValue *value,
319                                        GParamSpec *pspec)
320 {
321   EmpathyContactSelector *contact_selector = EMPATHY_CONTACT_SELECTOR (object);
322   EmpathyContactSelectorPriv *priv = GET_PRIV (contact_selector);
323
324   switch (prop_id)
325     {
326       case PROP_STORE:
327         g_value_set_object (value, priv->store);
328         break;
329       default:
330         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
331         break;
332     }
333 }
334
335
336 static void
337 empathy_contact_selector_dispose (GObject *object)
338 {
339   g_debug ("EmpathyContactSelector - dispose: %p",  object);
340
341   (G_OBJECT_CLASS (empathy_contact_selector_parent_class)->dispose) (object);
342 }
343
344
345 static void
346 empathy_contact_selector_finalize (GObject *object)
347 {
348   g_debug ("EmpathyContactSelector - finalize: %p",  object);
349
350   (G_OBJECT_CLASS (empathy_contact_selector_parent_class)->finalize) (object);
351 }
352
353
354 static void
355 empathy_contact_selector_class_init (EmpathyContactSelectorClass *klass)
356 {
357   GObjectClass *object_class = G_OBJECT_CLASS (klass);
358   object_class->constructor = empathy_contact_selector_constructor;
359   object_class->dispose = empathy_contact_selector_dispose;
360   object_class->finalize = empathy_contact_selector_finalize;
361   object_class->set_property = empathy_contact_selector_set_property;
362   object_class->get_property = empathy_contact_selector_get_property;
363   g_type_class_add_private (klass, sizeof (EmpathyContactSelectorPriv));
364
365   g_object_class_install_property (object_class, PROP_STORE,
366       g_param_spec_object ("store", "store", "store",
367       EMPATHY_TYPE_CONTACT_LIST_STORE, G_PARAM_CONSTRUCT_ONLY |
368       G_PARAM_READWRITE | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
369 }
370
371
372 EmpathyContactSelector *
373 empathy_contact_selector_new (EmpathyContactListStore *store)
374 {
375   return g_object_new (EMPATHY_TYPE_CONTACT_SELECTOR, "store", store, NULL);
376 }