]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-contact-selector.c
add translation function call
[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 <libempathy/empathy-utils.h>
31
32 #include "empathy-contact-selector.h"
33
34 G_DEFINE_TYPE (EmpathyContactSelector, empathy_contact_selector,
35     GTK_TYPE_COMBO_BOX)
36
37 enum
38 {
39   PROP_0,
40   PROP_STORE
41 };
42
43 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyContactSelector)
44 typedef struct
45 {
46   EmpathyContactListStore *store;
47   gboolean is_blank_set;
48 } EmpathyContactSelectorPriv;
49
50 static void changed_cb (GtkComboBox *widget, gpointer data);
51
52
53 EmpathyContact *
54 empathy_contact_selector_get_selected (EmpathyContactSelector *selector)
55 {
56   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
57   EmpathyContact *contact = NULL;
58   GtkTreeIter iter;
59
60   if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (selector), &iter))
61     return NULL;
62
63   gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
64       EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, &contact, -1);
65
66   return contact;
67 }
68
69
70 static guint
71 get_number_online_contacts (GtkTreeStore *store)
72 {
73   GtkTreePath *path;
74   GtkTreeIter tmp_iter;
75   gboolean is_online;
76   guint number_online_contacts = 0;
77
78   path = gtk_tree_path_new_first ();
79
80   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &tmp_iter, path))
81     {
82       do
83         {
84           gtk_tree_model_get (GTK_TREE_MODEL (store),
85               &tmp_iter, EMPATHY_CONTACT_LIST_STORE_COL_IS_ONLINE,
86               &is_online, -1);
87           if (is_online)
88             number_online_contacts++;
89         } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &tmp_iter));
90     }
91
92   gtk_tree_path_free (path);
93
94   return number_online_contacts;
95 }
96
97
98 static gboolean
99 get_iter_for_blank_contact (GtkTreeStore *store,
100                             GtkTreeIter *blank_iter)
101 {
102   GtkTreePath *path;
103   GtkTreeIter tmp_iter;
104   EmpathyContact *tmp_contact;
105   gboolean is_present = FALSE;
106
107   path = gtk_tree_path_new_first ();
108
109   if (gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &tmp_iter, path))
110     {
111       do
112         {
113           gtk_tree_model_get (GTK_TREE_MODEL (store),
114               &tmp_iter, EMPATHY_CONTACT_LIST_STORE_COL_CONTACT,
115               &tmp_contact, -1);
116           if (tmp_contact == NULL)
117             {
118               *blank_iter = tmp_iter;
119               is_present = TRUE;
120               break;
121             }
122         } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &tmp_iter));
123     }
124
125   gtk_tree_path_free (path);
126
127   return is_present;
128 }
129
130
131 static void
132 add_blank_contact (EmpathyContactSelector *selector)
133 {
134   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
135   GtkTreeIter blank_iter;
136
137   gtk_tree_store_insert (GTK_TREE_STORE (priv->store), &blank_iter, NULL, 0);
138   gtk_tree_store_set (GTK_TREE_STORE (priv->store), &blank_iter,
139       EMPATHY_CONTACT_LIST_STORE_COL_CONTACT, NULL,
140       EMPATHY_CONTACT_LIST_STORE_COL_NAME, (_("Select a contact")),
141       EMPATHY_CONTACT_LIST_STORE_COL_IS_ONLINE, FALSE, -1);
142   g_signal_handlers_block_by_func(selector, changed_cb, NULL);
143   gtk_combo_box_set_active_iter (GTK_COMBO_BOX (selector), &blank_iter);
144   g_signal_handlers_unblock_by_func(selector, changed_cb, NULL);
145   priv->is_blank_set = TRUE;
146 }
147
148
149 static void
150 remove_blank_contact (EmpathyContactSelector *selector)
151 {
152   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
153   GtkTreeIter blank_iter;
154
155   if (get_iter_for_blank_contact (GTK_TREE_STORE (priv->store), &blank_iter))
156     {
157       gtk_tree_store_remove (GTK_TREE_STORE (priv->store), &blank_iter);
158       priv->is_blank_set = FALSE;
159     }
160 }
161
162
163 static void
164 manage_sensitivity (EmpathyContactSelector *selector)
165 {
166   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
167   guint number_online_contacts =
168       get_number_online_contacts (GTK_TREE_STORE (priv->store));
169
170   if (number_online_contacts == 0 && priv->is_blank_set)
171       gtk_widget_set_sensitive (GTK_WIDGET (selector), FALSE);
172   else if (number_online_contacts)
173       gtk_widget_set_sensitive (GTK_WIDGET (selector), TRUE);
174   else
175       gtk_widget_set_sensitive (GTK_WIDGET (selector), FALSE);
176 }
177
178
179 static void
180 manage_blank_contact (EmpathyContactSelector *selector)
181 {
182   gboolean is_popup_shown;
183
184   g_object_get (selector, "popup-shown", &is_popup_shown, NULL);
185
186   if (is_popup_shown)
187     {
188       remove_blank_contact (selector);
189     }
190   else
191     {
192       if (gtk_combo_box_get_active (GTK_COMBO_BOX (selector)) == -1)
193         {
194           add_blank_contact (selector);
195         }
196       else
197         {
198           remove_blank_contact (selector);
199         }
200     }
201
202     manage_sensitivity (selector);
203 }
204
205
206 static void
207 notify_popup_shown_cb (GtkComboBox *widget,
208                        GParamSpec *property,
209                        gpointer data)
210 {
211   EmpathyContactSelector *selector = EMPATHY_CONTACT_SELECTOR (widget);
212
213   manage_blank_contact (selector);
214 }
215
216
217 static void
218 changed_cb (GtkComboBox *widget,
219             gpointer data)
220 {
221   EmpathyContactSelector *selector = EMPATHY_CONTACT_SELECTOR (widget);
222
223   manage_blank_contact (selector);
224 }
225
226
227 static void
228 empathy_store_row_changed_cb (EmpathyContactListStore *empathy_store,
229                               GtkTreePath *empathy_path,
230                               GtkTreeIter *empathy_iter,
231                               gpointer data)
232 {
233   EmpathyContactSelector *selector = EMPATHY_CONTACT_SELECTOR (data);
234
235   manage_sensitivity (selector);
236 }
237
238
239 static GObject *
240 empathy_contact_selector_constructor (GType type,
241                                       guint n_construct_params,
242                                       GObjectConstructParam *construct_params)
243 {
244   GObject *object =
245       G_OBJECT_CLASS (empathy_contact_selector_parent_class)->constructor (type,
246       n_construct_params, construct_params);
247   EmpathyContactSelector *contact_selector = EMPATHY_CONTACT_SELECTOR (object);
248   EmpathyContactSelectorPriv *priv = GET_PRIV (contact_selector);
249   GtkCellRenderer *renderer;
250
251   g_object_set (priv->store, "is-compact", TRUE, "show-avatars", FALSE,
252       "show-offline", FALSE, "show-groups", FALSE,
253       "sort-criterium", EMPATHY_CONTACT_LIST_STORE_SORT_NAME, NULL);
254
255   g_signal_connect (priv->store, "row-changed",
256       G_CALLBACK (empathy_store_row_changed_cb), (gpointer) contact_selector);
257   g_signal_connect (GTK_COMBO_BOX (contact_selector), "changed",
258       G_CALLBACK (changed_cb), NULL);
259   g_signal_connect (GTK_COMBO_BOX (contact_selector), "notify::popup-shown",
260       G_CALLBACK (notify_popup_shown_cb), NULL);
261
262   gtk_combo_box_set_model (GTK_COMBO_BOX (contact_selector),
263       GTK_TREE_MODEL (priv->store));
264   gtk_widget_set_sensitive (GTK_WIDGET (contact_selector), FALSE);
265
266   renderer = gtk_cell_renderer_pixbuf_new ();
267   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (contact_selector),
268       renderer, FALSE);
269   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (contact_selector), renderer,
270       "icon-name", EMPATHY_CONTACT_LIST_STORE_COL_ICON_STATUS, NULL);
271
272   renderer = gtk_cell_renderer_text_new ();
273   gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (contact_selector),
274       renderer, TRUE);
275   gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (contact_selector), renderer,
276       "text", EMPATHY_CONTACT_LIST_STORE_COL_NAME, NULL);
277
278   manage_blank_contact (contact_selector);
279   manage_sensitivity (contact_selector);
280
281   object = G_OBJECT (contact_selector);
282   return object;
283 }
284
285
286 static void
287 empathy_contact_selector_init (EmpathyContactSelector *empathy_contact_selector)
288 {
289   EmpathyContactSelectorPriv *priv =
290       G_TYPE_INSTANCE_GET_PRIVATE (empathy_contact_selector,
291       EMPATHY_TYPE_CONTACT_SELECTOR, EmpathyContactSelectorPriv);
292
293   empathy_contact_selector->priv = priv;
294 }
295
296
297 static void
298 empathy_contact_selector_set_property (GObject *object,
299                                        guint prop_id,
300                                        const GValue *value,
301                                        GParamSpec *pspec)
302 {
303   EmpathyContactSelector *contact_selector = EMPATHY_CONTACT_SELECTOR (object);
304   EmpathyContactSelectorPriv *priv = GET_PRIV (contact_selector);
305
306   switch (prop_id)
307     {
308       case PROP_STORE:
309         priv->store = g_value_dup_object (value);
310         break;
311       default:
312         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
313         break;
314     }
315 }
316
317
318 static void
319 empathy_contact_selector_get_property (GObject *object,
320                                        guint prop_id,
321                                        GValue *value,
322                                        GParamSpec *pspec)
323 {
324   EmpathyContactSelector *contact_selector = EMPATHY_CONTACT_SELECTOR (object);
325   EmpathyContactSelectorPriv *priv = GET_PRIV (contact_selector);
326
327   switch (prop_id)
328     {
329       case PROP_STORE:
330         g_value_set_object (value, priv->store);
331         break;
332       default:
333         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
334         break;
335     }
336 }
337
338
339 static void
340 empathy_contact_selector_dispose (GObject *object)
341 {
342   EmpathyContactSelector *selector = EMPATHY_CONTACT_SELECTOR (object);
343   EmpathyContactSelectorPriv *priv = GET_PRIV (selector);
344
345   if (priv->store)
346     {
347       g_object_unref (priv->store);
348       priv->store = NULL;
349     }
350
351   (G_OBJECT_CLASS (empathy_contact_selector_parent_class)->dispose) (object);
352 }
353
354
355 static void
356 empathy_contact_selector_class_init (EmpathyContactSelectorClass *klass)
357 {
358   GObjectClass *object_class = G_OBJECT_CLASS (klass);
359   object_class->constructor = empathy_contact_selector_constructor;
360   object_class->dispose = empathy_contact_selector_dispose;
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 }