]> git.0d.be Git - empathy.git/blob - src/empathy-preferences.c
Add preference to show account balances
[empathy.git] / src / empathy-preferences.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2003-2007 Imendio AB
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program 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  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA  02110-1301  USA
19  *
20  * Authors: Mikael Hallendal <micke@imendio.com>
21  *          Richard Hult <richard@imendio.com>
22  *          Martyn Russell <martyn@imendio.com>
23  *          Danielle Madeley <danielle.madeley@collabora.co.uk>
24  */
25
26 #include <config.h>
27
28 #include <string.h>
29 #include <stdio.h>
30
31 #include <gtk/gtk.h>
32 #include <glib/gi18n.h>
33 #include <telepathy-glib/dbus.h>
34 #include <telepathy-glib/util.h>
35
36 #include <libempathy/empathy-gsettings.h>
37 #include <libempathy/empathy-utils.h>
38
39 #include <libempathy-gtk/empathy-ui-utils.h>
40 #include <libempathy-gtk/empathy-theme-manager.h>
41 #include <libempathy-gtk/empathy-spell.h>
42 #include <libempathy-gtk/empathy-gtk-enum-types.h>
43 #include <libempathy-gtk/empathy-theme-adium.h>
44
45 #include "empathy-preferences.h"
46
47 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
48 #include <libempathy/empathy-debug.h>
49
50 G_DEFINE_TYPE (EmpathyPreferences, empathy_preferences, GTK_TYPE_DIALOG);
51
52 #define GET_PRIV(self) ((EmpathyPreferencesPriv *)((EmpathyPreferences *) self)->priv)
53
54 static const gchar * empathy_preferences_tabs[] =
55 {
56   "general",
57   "notifications",
58   "sounds",
59   "calls",
60   "location",
61   "spell",
62   "themes",
63 };
64
65 struct _EmpathyPreferencesPriv {
66         GtkWidget *notebook;
67
68         GtkWidget *checkbutton_events_notif_area;
69
70         GtkWidget *treeview_sounds;
71         GtkWidget *treeview_spell_checker;
72
73         GtkWidget *vbox_chat_theme;
74         GtkWidget *combobox_chat_theme;
75         GtkWidget *combobox_chat_theme_variant;
76         GtkWidget *hbox_chat_theme_variant;
77         GtkWidget *sw_chat_theme_preview;
78         EmpathyChatView *chat_theme_preview;
79         EmpathyThemeManager *theme_manager;
80
81         GSettings *gsettings;
82         GSettings *gsettings_chat;
83         GSettings *gsettings_call;
84         GSettings *gsettings_loc;
85         GSettings *gsettings_notify;
86         GSettings *gsettings_sound;
87         GSettings *gsettings_ui;
88         GSettings *gsettings_logger;
89         GSettings *gsettings_contacts;
90 };
91
92 static void     preferences_setup_widgets                (EmpathyPreferences      *preferences,
93                                                           GtkBuilder              *gui);
94 static void     preferences_languages_setup              (EmpathyPreferences      *preferences);
95 static void     preferences_languages_add                (EmpathyPreferences      *preferences);
96 static void     preferences_languages_save               (EmpathyPreferences      *preferences);
97 static gboolean preferences_languages_save_foreach       (GtkTreeModel           *model,
98                                                           GtkTreePath            *path,
99                                                           GtkTreeIter            *iter,
100                                                           gchar                 **languages);
101 static void     preferences_languages_load               (EmpathyPreferences      *preferences);
102 static gboolean preferences_languages_load_foreach       (GtkTreeModel           *model,
103                                                           GtkTreePath            *path,
104                                                           GtkTreeIter            *iter,
105                                                           GList                  *languages);
106 static void     preferences_languages_cell_toggled_cb    (GtkCellRendererToggle  *cell,
107                                                           gchar                  *path_string,
108                                                           EmpathyPreferences      *preferences);
109
110 enum {
111         COL_LANG_ENABLED,
112         COL_LANG_CODE,
113         COL_LANG_NAME,
114         COL_LANG_COUNT
115 };
116
117 enum {
118         COL_THEME_VISIBLE_NAME,
119         COL_THEME_NAME,
120         COL_THEME_IS_ADIUM,
121         COL_THEME_ADIUM_PATH,
122         COL_THEME_ADIUM_INFO,
123         COL_THEME_COUNT
124 };
125
126 enum {
127         COL_VARIANT_NAME,
128         COL_VARIANT_DEFAULT,
129         COL_VARIANT_COUNT
130 };
131
132 enum {
133         COL_SOUND_ENABLED,
134         COL_SOUND_NAME,
135         COL_SOUND_KEY,
136         COL_SOUND_COUNT
137 };
138
139 typedef struct {
140         const char *name;
141         const char *key;
142 } SoundEventEntry;
143
144 /* TODO: add phone related sounds also? */
145 static SoundEventEntry sound_entries [] = {
146         { N_("Message received"), EMPATHY_PREFS_SOUNDS_INCOMING_MESSAGE },
147         { N_("Message sent"), EMPATHY_PREFS_SOUNDS_OUTGOING_MESSAGE },
148         { N_("New conversation"), EMPATHY_PREFS_SOUNDS_NEW_CONVERSATION },
149         { N_("Contact comes online"), EMPATHY_PREFS_SOUNDS_CONTACT_LOGIN },
150         { N_("Contact goes offline"), EMPATHY_PREFS_SOUNDS_CONTACT_LOGOUT },
151         { N_("Account connected"), EMPATHY_PREFS_SOUNDS_SERVICE_LOGIN },
152         { N_("Account disconnected"), EMPATHY_PREFS_SOUNDS_SERVICE_LOGOUT }
153 };
154
155 static gboolean
156 sort_criterium_get_mapping (GValue *value,
157                             GVariant *variant,
158                             gpointer user_data)
159 {
160         const char *s = g_variant_get_string (variant, NULL);
161
162         if (!tp_strdiff (s, "state"))
163                 g_value_set_boolean (value, TRUE);
164         else if (!tp_strdiff (s, "name"))
165                 g_value_set_boolean (value, FALSE);
166         else
167                 return FALSE;
168
169         return TRUE;
170 }
171
172 static GVariant *
173 sort_criterium_set_mapping (const GValue *value,
174                             const GVariantType *expected_type,
175                             gpointer user_data)
176 {
177         gboolean b = g_value_get_boolean (value);
178
179         if (b)
180                 return g_variant_new_string ("state");
181         else
182                 return g_variant_new_string ("name");
183 }
184
185 static void
186 preferences_setup_widgets (EmpathyPreferences *preferences,
187                            GtkBuilder *gui)
188 {
189         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
190 #define BIND_ACTIVE(schema, key, widget) \
191         g_settings_bind (priv->gsettings_##schema, EMPATHY_PREFS_##key, \
192                          gtk_builder_get_object (gui, widget), "active", \
193                          G_SETTINGS_BIND_DEFAULT);
194
195         BIND_ACTIVE (notify, NOTIFICATIONS_ENABLED,
196                      "checkbutton_notifications_enabled");
197         BIND_ACTIVE (notify, NOTIFICATIONS_DISABLED_AWAY,
198                      "checkbutton_notifications_disabled_away");
199         BIND_ACTIVE (notify, NOTIFICATIONS_FOCUS,
200                      "checkbutton_notifications_focus");
201         BIND_ACTIVE (notify, NOTIFICATIONS_CONTACT_SIGNIN,
202                      "checkbutton_notifications_contact_signin");
203         BIND_ACTIVE (notify, NOTIFICATIONS_CONTACT_SIGNOUT,
204                      "checkbutton_notifications_contact_signout");
205
206         BIND_ACTIVE (sound, SOUNDS_ENABLED,
207                      "checkbutton_sounds_enabled");
208         BIND_ACTIVE (sound, SOUNDS_DISABLED_AWAY,
209                      "checkbutton_sounds_disabled_away");
210
211         BIND_ACTIVE (ui, UI_SHOW_OFFLINE,
212                      "checkbutton_show_offline");
213         BIND_ACTIVE (ui, UI_SHOW_PROTOCOLS,
214                      "checkbutton_show_protocols");
215         BIND_ACTIVE (ui, UI_SEPARATE_CHAT_WINDOWS,
216                      "radiobutton_chats_new_windows");
217         BIND_ACTIVE (ui, UI_EVENTS_NOTIFY_AREA,
218                      "checkbutton_events_notif_area");
219         BIND_ACTIVE (ui, UI_SHOW_AVATARS,
220                      "radiobutton_normal_size_avatars");
221         BIND_ACTIVE (ui, UI_COMPACT_CONTACT_LIST,
222                      "radiobutton_compact_size");
223         BIND_ACTIVE (ui, UI_SHOW_BALANCES,
224                      "checkbutton_show_balances");
225
226         BIND_ACTIVE (chat, CHAT_SHOW_SMILEYS,
227                      "checkbutton_show_smileys");
228         BIND_ACTIVE (chat, CHAT_SHOW_CONTACTS_IN_ROOMS,
229                      "checkbutton_show_contacts_in_rooms");
230
231         BIND_ACTIVE (call, CALL_ECHO_CANCELLATION,
232                      "call_echo_cancellation");
233
234         BIND_ACTIVE (loc, LOCATION_PUBLISH,
235                      "checkbutton_location_publish");
236         BIND_ACTIVE (loc, LOCATION_RESOURCE_NETWORK,
237                      "checkbutton_location_resource_network");
238         BIND_ACTIVE (loc, LOCATION_RESOURCE_CELL,
239                      "checkbutton_location_resource_cell");
240         BIND_ACTIVE (loc, LOCATION_RESOURCE_GPS,
241                      "checkbutton_location_resource_gps");
242         BIND_ACTIVE (loc, LOCATION_REDUCE_ACCURACY,
243                      "checkbutton_location_reduce_accuracy");
244
245         BIND_ACTIVE (logger, LOGGER_ENABLED,
246                      "checkbutton_logging");
247
248 #undef BIND_ACTIVE
249
250 #define BIND_SENSITIVE(schema, key, widget) \
251         g_settings_bind (priv->gsettings_##schema, EMPATHY_PREFS_##key, \
252                          gtk_builder_get_object (gui, widget), "sensitive", \
253                         G_SETTINGS_BIND_GET);
254         /* N.B. BIND_SENSITIVE() is in addition to the sensitivity setting of
255          *      BIND_ACTIVE() */
256         BIND_SENSITIVE (notify, NOTIFICATIONS_ENABLED,
257                         "checkbutton_notifications_disabled_away");
258         BIND_SENSITIVE (notify, NOTIFICATIONS_ENABLED,
259                         "checkbutton_notifications_focus");
260         BIND_SENSITIVE (notify, NOTIFICATIONS_ENABLED,
261                         "checkbutton_notifications_contact_signin");
262         BIND_SENSITIVE (notify, NOTIFICATIONS_ENABLED,
263                         "checkbutton_notifications_contact_signout");
264
265         BIND_SENSITIVE (sound, SOUNDS_ENABLED,
266                         "checkbutton_sounds_disabled_away");
267         BIND_SENSITIVE (sound, SOUNDS_ENABLED,
268                         "treeview_sounds");
269
270         BIND_SENSITIVE (loc, LOCATION_PUBLISH,
271                         "checkbutton_location_resource_network");
272         BIND_SENSITIVE (loc, LOCATION_PUBLISH,
273                         "checkbutton_location_resource_cell");
274         BIND_SENSITIVE (loc, LOCATION_PUBLISH,
275                         "checkbutton_location_resource_gps");
276         BIND_SENSITIVE (loc, LOCATION_PUBLISH,
277                         "checkbutton_location_reduce_accuracy");
278
279 #undef BIND_SENSITIVE
280
281         g_settings_bind (priv->gsettings,
282                          EMPATHY_PREFS_AUTOCONNECT,
283                          gtk_builder_get_object (gui,
284                                                  "checkbutton_autoconnect"),
285                          "active",
286                          G_SETTINGS_BIND_DEFAULT);
287
288         g_settings_bind_with_mapping (priv->gsettings_contacts,
289                          EMPATHY_PREFS_CONTACTS_SORT_CRITERIUM,
290                          gtk_builder_get_object (gui,
291                                                  "radiobutton_sort_by_status"),
292                          "active",
293                          G_SETTINGS_BIND_DEFAULT,
294                          sort_criterium_get_mapping,
295                          sort_criterium_set_mapping,
296                          NULL, NULL);
297 }
298
299 static void
300 preferences_sound_cell_toggled_cb (GtkCellRendererToggle *toggle,
301                                    char *path_string,
302                                    EmpathyPreferences *preferences)
303 {
304         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
305         GtkTreePath *path;
306         gboolean instore;
307         GtkTreeIter iter;
308         GtkTreeView *view;
309         GtkTreeModel *model;
310         char *key;
311
312         view = GTK_TREE_VIEW (priv->treeview_sounds);
313         model = gtk_tree_view_get_model (view);
314
315         path = gtk_tree_path_new_from_string (path_string);
316
317         gtk_tree_model_get_iter (model, &iter, path);
318         gtk_tree_model_get (model, &iter, COL_SOUND_KEY, &key,
319                             COL_SOUND_ENABLED, &instore, -1);
320
321         instore ^= 1;
322
323         gtk_list_store_set (GTK_LIST_STORE (model), &iter,
324                             COL_SOUND_ENABLED, instore, -1);
325
326         g_settings_set_boolean (priv->gsettings_sound, key, instore);
327
328         g_free (key);
329         gtk_tree_path_free (path);
330 }
331
332 static void
333 preferences_sound_load (EmpathyPreferences *preferences)
334 {
335         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
336         guint i;
337         GtkTreeView *view;
338         GtkListStore *store;
339         GtkTreeIter iter;
340         gboolean set;
341
342         view = GTK_TREE_VIEW (priv->treeview_sounds);
343         store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
344
345         for (i = 0; i < G_N_ELEMENTS (sound_entries); i++) {
346                 set = g_settings_get_boolean (priv->gsettings_sound,
347                                               sound_entries[i].key);
348
349                 gtk_list_store_insert_with_values (store, &iter, i,
350                                                    COL_SOUND_NAME, gettext (sound_entries[i].name),
351                                                    COL_SOUND_KEY, sound_entries[i].key,
352                                                    COL_SOUND_ENABLED, set, -1);
353         }
354 }
355
356 static void
357 preferences_sound_setup (EmpathyPreferences *preferences)
358 {
359         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
360         GtkTreeView *view;
361         GtkListStore *store;
362         GtkCellRenderer *renderer;
363         GtkTreeViewColumn *column;
364
365         view = GTK_TREE_VIEW (priv->treeview_sounds);
366
367         store = gtk_list_store_new (COL_SOUND_COUNT,
368                                     G_TYPE_BOOLEAN, /* enabled */
369                                     G_TYPE_STRING,  /* name */
370                                     G_TYPE_STRING); /* key */
371
372         gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
373
374         renderer = gtk_cell_renderer_toggle_new ();
375         g_signal_connect (renderer, "toggled",
376                           G_CALLBACK (preferences_sound_cell_toggled_cb),
377                           preferences);
378
379         column = gtk_tree_view_column_new ();
380         gtk_tree_view_column_pack_start (column, renderer, FALSE);
381         gtk_tree_view_column_add_attribute (column, renderer,
382                                             "active", COL_SOUND_ENABLED);
383
384         renderer = gtk_cell_renderer_text_new ();
385         gtk_tree_view_column_pack_start (column, renderer, FALSE);
386         gtk_tree_view_column_add_attribute (column, renderer,
387                                             "text", COL_SOUND_NAME);
388
389         gtk_tree_view_append_column (view, column);
390
391         gtk_tree_view_column_set_resizable (column, FALSE);
392         gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
393
394         g_object_unref (store);
395 }
396
397 static void
398 preferences_languages_setup (EmpathyPreferences *preferences)
399 {
400         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
401         GtkTreeView       *view;
402         GtkListStore      *store;
403         GtkTreeSelection  *selection;
404         GtkTreeViewColumn *column;
405         GtkCellRenderer   *renderer;
406         guint              col_offset;
407
408         view = GTK_TREE_VIEW (priv->treeview_spell_checker);
409
410         store = gtk_list_store_new (COL_LANG_COUNT,
411                                     G_TYPE_BOOLEAN,  /* enabled */
412                                     G_TYPE_STRING,   /* code */
413                                     G_TYPE_STRING);  /* name */
414
415         gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
416
417         selection = gtk_tree_view_get_selection (view);
418         gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
419
420         renderer = gtk_cell_renderer_toggle_new ();
421         g_signal_connect (renderer, "toggled",
422                           G_CALLBACK (preferences_languages_cell_toggled_cb),
423                           preferences);
424
425         column = gtk_tree_view_column_new_with_attributes (NULL, renderer,
426                                                            "active", COL_LANG_ENABLED,
427                                                            NULL);
428
429         gtk_tree_view_append_column (view, column);
430
431         renderer = gtk_cell_renderer_text_new ();
432         col_offset = gtk_tree_view_insert_column_with_attributes (view,
433                                                                   -1, _("Language"),
434                                                                   renderer,
435                                                                   "text", COL_LANG_NAME,
436                                                                   NULL);
437
438         g_object_set_data (G_OBJECT (renderer),
439                            "column", GINT_TO_POINTER (COL_LANG_NAME));
440
441         column = gtk_tree_view_get_column (view, col_offset - 1);
442         gtk_tree_view_column_set_sort_column_id (column, COL_LANG_NAME);
443         gtk_tree_view_column_set_resizable (column, FALSE);
444         gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
445
446         g_object_unref (store);
447 }
448
449 static void
450 preferences_languages_add (EmpathyPreferences *preferences)
451 {
452         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
453         GtkTreeView  *view;
454         GtkListStore *store;
455         GList        *codes, *l;
456
457         view = GTK_TREE_VIEW (priv->treeview_spell_checker);
458         store = GTK_LIST_STORE (gtk_tree_view_get_model (view));
459
460         codes = empathy_spell_get_language_codes ();
461
462         if (!codes) {
463                 gtk_widget_set_sensitive (priv->treeview_spell_checker, FALSE);
464         }
465
466         for (l = codes; l; l = l->next) {
467                 const gchar *code;
468                 const gchar *name;
469
470                 code = l->data;
471                 name = empathy_spell_get_language_name (code);
472                 if (!name) {
473                         continue;
474                 }
475
476                 gtk_list_store_insert_with_values (store, NULL, -1,
477                                     COL_LANG_CODE, code,
478                                     COL_LANG_NAME, name,
479                                     -1);
480         }
481
482         empathy_spell_free_language_codes (codes);
483 }
484
485 static void
486 preferences_languages_save (EmpathyPreferences *preferences)
487 {
488         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
489         GtkTreeView       *view;
490         GtkTreeModel      *model;
491
492         gchar             *languages = NULL;
493
494         view = GTK_TREE_VIEW (priv->treeview_spell_checker);
495         model = gtk_tree_view_get_model (view);
496
497         gtk_tree_model_foreach (model,
498                                 (GtkTreeModelForeachFunc) preferences_languages_save_foreach,
499                                 &languages);
500
501         /* if user selects no languages, we don't want spell check */
502         g_settings_set_boolean (priv->gsettings_chat,
503                                 EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED,
504                                 languages != NULL);
505
506         g_settings_set_string (priv->gsettings_chat,
507                                EMPATHY_PREFS_CHAT_SPELL_CHECKER_LANGUAGES,
508                                languages != NULL ? languages : "");
509
510         g_free (languages);
511 }
512
513 static gboolean
514 preferences_languages_save_foreach (GtkTreeModel  *model,
515                                     GtkTreePath   *path,
516                                     GtkTreeIter   *iter,
517                                     gchar        **languages)
518 {
519         gboolean  enabled;
520         gchar    *code;
521
522         if (!languages) {
523                 return TRUE;
524         }
525
526         gtk_tree_model_get (model, iter, COL_LANG_ENABLED, &enabled, -1);
527         if (!enabled) {
528                 return FALSE;
529         }
530
531         gtk_tree_model_get (model, iter, COL_LANG_CODE, &code, -1);
532         if (!code) {
533                 return FALSE;
534         }
535
536         if (!(*languages)) {
537                 *languages = g_strdup (code);
538         } else {
539                 gchar *str = *languages;
540                 *languages = g_strdup_printf ("%s,%s", str, code);
541                 g_free (str);
542         }
543
544         g_free (code);
545
546         return FALSE;
547 }
548
549 static void
550 preferences_languages_load (EmpathyPreferences *preferences)
551 {
552         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
553         GtkTreeView   *view;
554         GtkTreeModel  *model;
555         GList         *enabled_codes;
556
557         enabled_codes = empathy_spell_get_enabled_language_codes ();
558
559         g_settings_set_boolean (priv->gsettings_chat,
560                                 EMPATHY_PREFS_CHAT_SPELL_CHECKER_ENABLED,
561                                 enabled_codes != NULL);
562
563         if (enabled_codes == NULL)
564                 return;
565
566         view = GTK_TREE_VIEW (priv->treeview_spell_checker);
567         model = gtk_tree_view_get_model (view);
568
569         gtk_tree_model_foreach (model,
570                                 (GtkTreeModelForeachFunc) preferences_languages_load_foreach,
571                                 enabled_codes);
572
573         g_list_free (enabled_codes);
574 }
575
576 static gboolean
577 preferences_languages_load_foreach (GtkTreeModel  *model,
578                                     GtkTreePath   *path,
579                                     GtkTreeIter   *iter,
580                                     GList         *languages)
581 {
582         gchar    *code;
583         gboolean  found = FALSE;
584
585         if (!languages) {
586                 return TRUE;
587         }
588
589         gtk_tree_model_get (model, iter, COL_LANG_CODE, &code, -1);
590         if (!code) {
591                 return FALSE;
592         }
593
594         if (g_list_find_custom (languages, code, (GCompareFunc) strcmp)) {
595                 found = TRUE;
596         }
597
598         g_free (code);
599         gtk_list_store_set (GTK_LIST_STORE (model), iter, COL_LANG_ENABLED, found, -1);
600         return FALSE;
601 }
602
603 static void
604 preferences_languages_cell_toggled_cb (GtkCellRendererToggle *cell,
605                                        gchar                 *path_string,
606                                        EmpathyPreferences     *preferences)
607 {
608         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
609         GtkTreeView  *view;
610         GtkTreeModel *model;
611         GtkListStore *store;
612         GtkTreePath  *path;
613         GtkTreeIter   iter;
614         gboolean      enabled;
615
616         view = GTK_TREE_VIEW (priv->treeview_spell_checker);
617         model = gtk_tree_view_get_model (view);
618         store = GTK_LIST_STORE (model);
619
620         path = gtk_tree_path_new_from_string (path_string);
621
622         gtk_tree_model_get_iter (model, &iter, path);
623         gtk_tree_model_get (model, &iter, COL_LANG_ENABLED, &enabled, -1);
624
625         enabled ^= 1;
626
627         gtk_list_store_set (store, &iter, COL_LANG_ENABLED, enabled, -1);
628         gtk_tree_path_free (path);
629
630         preferences_languages_save (preferences);
631 }
632
633 static void
634 preferences_preview_theme_append_message (EmpathyChatView *view,
635                                           EmpathyContact *sender,
636                                           EmpathyContact *receiver,
637                                           const gchar *text,
638                                           gboolean should_highlight)
639 {
640         EmpathyMessage *message;
641
642         message = g_object_new (EMPATHY_TYPE_MESSAGE,
643                 "sender", sender,
644                 "receiver", receiver,
645                 "body", text,
646                 NULL);
647
648         empathy_chat_view_append_message (view, message, should_highlight);
649         g_object_unref (message);
650 }
651
652 static void
653 preferences_preview_theme_changed_cb (EmpathyThemeManager *manager,
654                                       EmpathyPreferences  *preferences)
655 {
656         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
657         TpDBusDaemon *dbus;
658         TpAccount *account;
659         EmpathyContact *juliet;
660         EmpathyContact *romeo;
661
662         DEBUG ("Theme changed, update preview widget");
663
664         if (priv->chat_theme_preview != NULL) {
665                 gtk_widget_destroy (GTK_WIDGET (priv->chat_theme_preview));
666         }
667         priv->chat_theme_preview = empathy_theme_manager_create_view (manager);
668         gtk_container_add (GTK_CONTAINER (priv->sw_chat_theme_preview),
669                            GTK_WIDGET (priv->chat_theme_preview));
670         gtk_widget_show (GTK_WIDGET (priv->chat_theme_preview));
671
672         /* FIXME: It is ugly to add a fake conversation like that.
673          * Would be cool if we could request a TplLogManager for a fake
674          * conversation */
675         dbus = tp_dbus_daemon_dup (NULL);
676         account = tp_account_new (dbus,
677                 TP_ACCOUNT_OBJECT_PATH_BASE "cm/jabber/account", NULL);
678         juliet = g_object_new (EMPATHY_TYPE_CONTACT,
679                 "account", account,
680                 "id", "juliet",
681                 /* translators: Contact name for the chat theme preview */
682                 "alias", _("Juliet"),
683                 "is-user", FALSE,
684                 NULL);
685         romeo = g_object_new (EMPATHY_TYPE_CONTACT,
686                 "account", account,
687                 "id", "romeo",
688                 /* translators: Contact name for the chat theme preview */
689                 "alias", _("Romeo"),
690                 "is-user", TRUE,
691                 NULL);
692
693         preferences_preview_theme_append_message (priv->chat_theme_preview,
694                 /* translators: Quote from Romeo & Julier, for chat theme preview */
695                 juliet, romeo, _("O Romeo, Romeo, wherefore art thou Romeo?"),
696                 TRUE /* this message mentions Romeo */);
697         preferences_preview_theme_append_message (priv->chat_theme_preview,
698                 /* translators: Quote from Romeo & Julier, for chat theme preview */
699                 juliet, romeo, _("Deny thy father and refuse thy name;"), FALSE);
700         preferences_preview_theme_append_message (priv->chat_theme_preview,
701                 /* translators: Quote from Romeo & Julier, for chat theme preview */
702                 juliet, romeo, _("Or if thou wilt not, be but sworn my love"), FALSE);
703         preferences_preview_theme_append_message (priv->chat_theme_preview,
704                 /* translators: Quote from Romeo & Julier, for chat theme preview */
705                 juliet, romeo, _("And I'll no longer be a Capulet."), FALSE);
706         preferences_preview_theme_append_message (priv->chat_theme_preview,
707                 /* translators: Quote from Romeo & Julier, for chat theme preview */
708                 romeo, juliet, _("Shall I hear more, or shall I speak at this?"), FALSE);
709
710         /* translators: Quote from Romeo & Julier, for chat theme preview */
711         empathy_chat_view_append_event (priv->chat_theme_preview, _("Juliet has disconnected"));
712
713         g_object_unref (juliet);
714         g_object_unref (romeo);
715         g_object_unref (account);
716         g_object_unref (dbus);
717 }
718
719 static void
720 preferences_theme_variant_changed_cb (GtkComboBox        *combo,
721                                       EmpathyPreferences *preferences)
722 {
723         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
724         GtkTreeIter   iter;
725
726         if (gtk_combo_box_get_active_iter (combo, &iter)) {
727                 GtkTreeModel *model;
728                 gchar        *name;
729
730                 model = gtk_combo_box_get_model (combo);
731                 gtk_tree_model_get (model, &iter,
732                                     COL_VARIANT_NAME, &name,
733                                     -1);
734
735                 g_settings_set_string (priv->gsettings_chat,
736                                        EMPATHY_PREFS_CHAT_THEME_VARIANT,
737                                        name);
738
739                 g_free (name);
740         }
741 }
742
743 static void
744 preferences_theme_variant_notify_cb (GSettings   *gsettings,
745                                      const gchar *key,
746                                      gpointer     user_data)
747 {
748         EmpathyPreferences *preferences = user_data;
749         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
750         GtkComboBox        *combo;
751         gchar              *conf_name;
752         GtkTreeModel       *model;
753         GtkTreeIter         iter;
754         GtkTreeIter         default_iter;
755         gboolean            found_default = FALSE;
756         gboolean            found = FALSE;
757         gboolean            ok;
758
759         conf_name = g_settings_get_string (gsettings, EMPATHY_PREFS_CHAT_THEME_VARIANT);
760         combo = GTK_COMBO_BOX (priv->combobox_chat_theme_variant);
761         model = gtk_combo_box_get_model (combo);
762
763         for (ok = gtk_tree_model_get_iter_first (model, &iter);
764              ok && !found;
765              ok = gtk_tree_model_iter_next (model, &iter)) {
766                 gchar *name;
767                 gboolean is_default;
768
769                 gtk_tree_model_get (model, &iter,
770                                     COL_VARIANT_NAME, &name,
771                                     COL_VARIANT_DEFAULT, &is_default,
772                                     -1);
773
774                 if (!tp_strdiff (name, conf_name)) {
775                         found = TRUE;
776                         gtk_combo_box_set_active_iter (combo, &iter);
777                 }
778                 if (is_default) {
779                         found_default = TRUE;
780                         default_iter = iter;
781                 }
782
783                 g_free (name);
784         }
785
786         /* Fallback to the first one. */
787         if (!found) {
788                 if (found_default) {
789                         gtk_combo_box_set_active_iter (combo, &default_iter);
790                 } else if (gtk_tree_model_get_iter_first (model, &iter)) {
791                         gtk_combo_box_set_active_iter (combo, &iter);
792                 }
793         }
794
795         g_free (conf_name);
796 }
797
798 /* return TRUE if we added at least one variant */
799 static gboolean
800 preferences_theme_variants_fill (EmpathyPreferences *preferences,
801                                  GHashTable         *info)
802 {
803         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
804         GtkTreeModel *model;
805         GtkListStore *store;
806         GPtrArray    *variants;
807         const gchar  *default_variant;
808         guint         i;
809         gboolean      result = FALSE;
810
811         model = gtk_combo_box_get_model (GTK_COMBO_BOX (priv->combobox_chat_theme_variant));
812         store = GTK_LIST_STORE (model);
813         gtk_list_store_clear (store);
814
815         variants = empathy_adium_info_get_available_variants (info);
816         default_variant = empathy_adium_info_get_default_variant (info);
817         for (i = 0; i < variants->len; i++) {
818                 gchar *name = g_ptr_array_index (variants, i);
819
820                 gtk_list_store_insert_with_values (store, NULL, -1,
821                         COL_VARIANT_NAME, name,
822                         COL_VARIANT_DEFAULT, !tp_strdiff (name, default_variant),
823                         -1);
824
825                 result = TRUE;
826         }
827
828         /* Select the variant from the GSetting key */
829         preferences_theme_variant_notify_cb (priv->gsettings_chat,
830                                              EMPATHY_PREFS_CHAT_THEME_VARIANT,
831                                              preferences);
832
833         return result;
834 }
835
836 static void
837 preferences_theme_variants_setup (EmpathyPreferences *preferences)
838 {
839         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
840         GtkComboBox   *combo;
841         GtkCellLayout *cell_layout;
842         GtkCellRenderer *renderer;
843         GtkListStore  *store;
844
845         combo = GTK_COMBO_BOX (priv->combobox_chat_theme_variant);
846         cell_layout = GTK_CELL_LAYOUT (combo);
847
848         /* Create the model */
849         store = gtk_list_store_new (COL_VARIANT_COUNT,
850                                     G_TYPE_STRING,      /* name */
851                                     G_TYPE_BOOLEAN);    /* is default */
852         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
853                 COL_VARIANT_NAME, GTK_SORT_ASCENDING);
854
855         /* Add cell renderer */
856         renderer = gtk_cell_renderer_text_new ();
857         gtk_cell_layout_pack_start (cell_layout, renderer, TRUE);
858         gtk_cell_layout_set_attributes (cell_layout, renderer,
859                 "text", COL_VARIANT_NAME, NULL);
860
861         gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
862         g_object_unref (store);
863
864         g_signal_connect (combo, "changed",
865                           G_CALLBACK (preferences_theme_variant_changed_cb),
866                           preferences);
867
868         /* Track changes of the GSetting key */
869         g_signal_connect (priv->gsettings_chat,
870                           "changed::" EMPATHY_PREFS_CHAT_THEME_VARIANT,
871                           G_CALLBACK (preferences_theme_variant_notify_cb),
872                           preferences);
873 }
874
875 static void
876 preferences_theme_changed_cb (GtkComboBox        *combo,
877                               EmpathyPreferences *preferences)
878 {
879         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
880         GtkTreeIter   iter;
881
882         if (gtk_combo_box_get_active_iter (combo, &iter)) {
883                 GtkTreeModel *model;
884                 gboolean      is_adium;
885                 gchar        *name;
886                 gchar        *path;
887                 GHashTable   *info;
888
889                 model = gtk_combo_box_get_model (combo);
890                 gtk_tree_model_get (model, &iter,
891                                     COL_THEME_IS_ADIUM, &is_adium,
892                                     COL_THEME_NAME, &name,
893                                     COL_THEME_ADIUM_PATH, &path,
894                                     COL_THEME_ADIUM_INFO, &info,
895                                     -1);
896
897                 g_settings_set_string (priv->gsettings_chat,
898                                        EMPATHY_PREFS_CHAT_THEME,
899                                        name);
900                 if (is_adium) {
901                         gboolean variant;
902
903                         g_settings_set_string (priv->gsettings_chat,
904                                                EMPATHY_PREFS_CHAT_ADIUM_PATH,
905                                                path);
906
907                         variant = preferences_theme_variants_fill (preferences, info);
908                         gtk_widget_set_visible (priv->hbox_chat_theme_variant, variant);
909                 } else {
910                         gtk_widget_hide (priv->hbox_chat_theme_variant);
911                 }
912                 g_free (name);
913                 g_free (path);
914                 tp_clear_pointer (&info, g_hash_table_unref);
915         }
916 }
917
918 static void
919 preferences_theme_notify_cb (GSettings   *gsettings,
920                              const gchar *key,
921                              gpointer     user_data)
922 {
923         EmpathyPreferences *preferences = user_data;
924         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
925         GtkComboBox        *combo;
926         gchar              *conf_name;
927         gchar              *conf_path;
928         GtkTreeModel       *model;
929         GtkTreeIter         iter;
930         gboolean            found = FALSE;
931         gboolean            ok;
932
933         conf_name = g_settings_get_string (gsettings, EMPATHY_PREFS_CHAT_THEME);
934         conf_path = g_settings_get_string (gsettings, EMPATHY_PREFS_CHAT_ADIUM_PATH);
935
936         combo = GTK_COMBO_BOX (priv->combobox_chat_theme);
937         model = gtk_combo_box_get_model (combo);
938         for (ok = gtk_tree_model_get_iter_first (model, &iter);
939              ok && !found;
940              ok = gtk_tree_model_iter_next (model, &iter)) {
941                 gboolean is_adium;
942                 gchar *name;
943                 gchar *path;
944
945                 gtk_tree_model_get (model, &iter,
946                                     COL_THEME_IS_ADIUM, &is_adium,
947                                     COL_THEME_NAME, &name,
948                                     COL_THEME_ADIUM_PATH, &path,
949                                     -1);
950
951                 if (!tp_strdiff (name, conf_name) &&
952                     (!is_adium || !tp_strdiff (path, conf_path))) {
953                         found = TRUE;
954                         gtk_combo_box_set_active_iter (combo, &iter);
955                 }
956
957                 g_free (name);
958                 g_free (path);
959         }
960
961         /* Fallback to the first one. */
962         if (!found) {
963                 if (gtk_tree_model_get_iter_first (model, &iter)) {
964                         gtk_combo_box_set_active_iter (combo, &iter);
965                 }
966         }
967
968         g_free (conf_name);
969         g_free (conf_path);
970 }
971
972 static void
973 preferences_themes_setup (EmpathyPreferences *preferences)
974 {
975         EmpathyPreferencesPriv *priv = GET_PRIV (preferences);
976         GtkComboBox   *combo;
977         GtkCellLayout *cell_layout;
978         GtkCellRenderer *renderer;
979         GtkListStore  *store;
980         const gchar  **themes;
981         GList         *adium_themes;
982         gint           i;
983
984         preferences_theme_variants_setup (preferences);
985
986         combo = GTK_COMBO_BOX (priv->combobox_chat_theme);
987         cell_layout = GTK_CELL_LAYOUT (combo);
988
989         /* Create the model */
990         store = gtk_list_store_new (COL_THEME_COUNT,
991                                     G_TYPE_STRING,      /* Display name */
992                                     G_TYPE_STRING,      /* Theme name */
993                                     G_TYPE_BOOLEAN,     /* Is an Adium theme */
994                                     G_TYPE_STRING,      /* Adium theme path */
995                                     G_TYPE_HASH_TABLE); /* Adium theme info */
996         gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
997                 COL_THEME_VISIBLE_NAME, GTK_SORT_ASCENDING);
998
999         /* Fill the model */
1000         themes = empathy_theme_manager_get_themes ();
1001         for (i = 0; themes[i]; i += 2) {
1002                 gtk_list_store_insert_with_values (store, NULL, -1,
1003                         COL_THEME_VISIBLE_NAME, _(themes[i + 1]),
1004                         COL_THEME_NAME, themes[i],
1005                         COL_THEME_IS_ADIUM, FALSE,
1006                         -1);
1007         }
1008
1009         adium_themes = empathy_theme_manager_get_adium_themes ();
1010         while (adium_themes != NULL) {
1011                 GHashTable *info;
1012                 const gchar *name;
1013                 const gchar *path;
1014
1015                 info = adium_themes->data;
1016                 name = tp_asv_get_string (info, "CFBundleName");
1017                 path = tp_asv_get_string (info, "path");
1018
1019                 if (name != NULL && path != NULL) {
1020                         gtk_list_store_insert_with_values (store, NULL, -1,
1021                                 COL_THEME_VISIBLE_NAME, name,
1022                                 COL_THEME_NAME, "adium",
1023                                 COL_THEME_IS_ADIUM, TRUE,
1024                                 COL_THEME_ADIUM_PATH, path,
1025                                 COL_THEME_ADIUM_INFO, info,
1026                                 -1);
1027                 }
1028                 g_hash_table_unref (info);
1029                 adium_themes = g_list_delete_link (adium_themes, adium_themes);
1030         }
1031
1032         /* Add cell renderer */
1033         renderer = gtk_cell_renderer_text_new ();
1034         gtk_cell_layout_pack_start (cell_layout, renderer, TRUE);
1035         gtk_cell_layout_set_attributes (cell_layout, renderer,
1036                 "text", COL_THEME_VISIBLE_NAME, NULL);
1037
1038         gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
1039         g_object_unref (store);
1040
1041         g_signal_connect (combo, "changed",
1042                           G_CALLBACK (preferences_theme_changed_cb),
1043                           preferences);
1044
1045         /* Select the theme from the GSetting key and track changes */
1046         preferences_theme_notify_cb (priv->gsettings_chat,
1047                                      EMPATHY_PREFS_CHAT_THEME,
1048                                      preferences);
1049         g_signal_connect (priv->gsettings_chat,
1050                           "changed::" EMPATHY_PREFS_CHAT_THEME,
1051                           G_CALLBACK (preferences_theme_notify_cb),
1052                           preferences);
1053
1054         g_signal_connect (priv->gsettings_chat,
1055                           "changed::" EMPATHY_PREFS_CHAT_ADIUM_PATH,
1056                           G_CALLBACK (preferences_theme_notify_cb),
1057                           preferences);
1058 }
1059
1060 static void
1061 empathy_preferences_response (GtkDialog *widget,
1062                               gint response)
1063 {
1064         gtk_widget_destroy (GTK_WIDGET (widget));
1065 }
1066
1067 static void
1068 empathy_preferences_finalize (GObject *self)
1069 {
1070         EmpathyPreferencesPriv *priv = GET_PRIV (self);
1071
1072         g_object_unref (priv->theme_manager);
1073
1074         g_object_unref (priv->gsettings);
1075         g_object_unref (priv->gsettings_chat);
1076         g_object_unref (priv->gsettings_call);
1077         g_object_unref (priv->gsettings_loc);
1078         g_object_unref (priv->gsettings_notify);
1079         g_object_unref (priv->gsettings_sound);
1080         g_object_unref (priv->gsettings_ui);
1081         g_object_unref (priv->gsettings_logger);
1082         g_object_unref (priv->gsettings_contacts);
1083
1084         G_OBJECT_CLASS (empathy_preferences_parent_class)->finalize (self);
1085 }
1086
1087 static void
1088 empathy_preferences_class_init (EmpathyPreferencesClass *klass)
1089 {
1090         GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
1091         GObjectClass *object_class = G_OBJECT_CLASS (klass);
1092
1093         dialog_class->response = empathy_preferences_response;
1094
1095         object_class->finalize = empathy_preferences_finalize;
1096
1097         g_type_class_add_private (object_class,
1098                                   sizeof (EmpathyPreferencesPriv));
1099 }
1100
1101 static void
1102 empathy_preferences_init (EmpathyPreferences *preferences)
1103 {
1104         EmpathyPreferencesPriv    *priv;
1105         GtkBuilder                *gui;
1106         gchar                     *filename;
1107         GtkWidget                 *page;
1108
1109         priv = preferences->priv = G_TYPE_INSTANCE_GET_PRIVATE (preferences,
1110                         EMPATHY_TYPE_PREFERENCES, EmpathyPreferencesPriv);
1111
1112         gtk_dialog_add_button (GTK_DIALOG (preferences),
1113                                GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
1114
1115         gtk_container_set_border_width (GTK_CONTAINER (preferences), 5);
1116         gtk_window_set_title (GTK_WINDOW (preferences), _("Preferences"));
1117         gtk_window_set_role (GTK_WINDOW (preferences), "preferences");
1118         gtk_window_set_position (GTK_WINDOW (preferences),
1119                                  GTK_WIN_POS_CENTER_ON_PARENT);
1120         gtk_window_set_icon_name (GTK_WINDOW (preferences), "gtk-preferences");
1121
1122         filename = empathy_file_lookup ("empathy-preferences.ui", "src");
1123         gui = empathy_builder_get_file (filename,
1124                 "notebook", &priv->notebook,
1125                 "vbox_chat_theme", &priv->vbox_chat_theme,
1126                 "combobox_chat_theme", &priv->combobox_chat_theme,
1127                 "combobox_chat_theme_variant", &priv->combobox_chat_theme_variant,
1128                 "hbox_chat_theme_variant", &priv->hbox_chat_theme_variant,
1129                 "sw_chat_theme_preview", &priv->sw_chat_theme_preview,
1130                 "checkbutton_events_notif_area", &priv->checkbutton_events_notif_area,
1131                 "treeview_sounds", &priv->treeview_sounds,
1132                 "treeview_spell_checker", &priv->treeview_spell_checker,
1133                 NULL);
1134         g_free (filename);
1135
1136         gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (preferences))), priv->notebook);
1137         gtk_widget_show (priv->notebook);
1138
1139         priv->gsettings = g_settings_new (EMPATHY_PREFS_SCHEMA);
1140         priv->gsettings_chat = g_settings_new (EMPATHY_PREFS_CHAT_SCHEMA);
1141         priv->gsettings_call = g_settings_new (EMPATHY_PREFS_CALL_SCHEMA);
1142         priv->gsettings_loc = g_settings_new (EMPATHY_PREFS_LOCATION_SCHEMA);
1143         priv->gsettings_notify = g_settings_new (EMPATHY_PREFS_NOTIFICATIONS_SCHEMA);
1144         priv->gsettings_sound = g_settings_new (EMPATHY_PREFS_SOUNDS_SCHEMA);
1145         priv->gsettings_ui = g_settings_new (EMPATHY_PREFS_UI_SCHEMA);
1146         priv->gsettings_logger = g_settings_new (EMPATHY_PREFS_LOGGER_SCHEMA);
1147         priv->gsettings_contacts = g_settings_new (EMPATHY_PREFS_CONTACTS_SCHEMA);
1148
1149         /* Create chat theme preview, and track changes */
1150         priv->theme_manager = empathy_theme_manager_dup_singleton ();
1151         tp_g_signal_connect_object (priv->theme_manager, "theme-changed",
1152                           G_CALLBACK (preferences_preview_theme_changed_cb),
1153                           preferences, 0);
1154         preferences_preview_theme_changed_cb (priv->theme_manager, preferences);
1155
1156         preferences_themes_setup (preferences);
1157
1158         preferences_setup_widgets (preferences, gui);
1159
1160         preferences_languages_setup (preferences);
1161         preferences_languages_add (preferences);
1162         preferences_languages_load (preferences);
1163
1164         preferences_sound_setup (preferences);
1165         preferences_sound_load (preferences);
1166
1167         g_object_unref (gui);
1168
1169         if (empathy_spell_supported ()) {
1170                 page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), EMPATHY_PREFERENCES_TAB_SPELL);
1171                 gtk_widget_show (page);
1172         }
1173
1174         page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook), EMPATHY_PREFERENCES_TAB_LOCATION);
1175 #ifdef HAVE_GEOCLUE
1176         gtk_widget_show (page);
1177 #else
1178         gtk_widget_hide (page);
1179 #endif
1180 }
1181
1182 static EmpathyPreferencesTab
1183 empathy_preferences_tab_from_string (const gchar *str)
1184 {
1185   guint i;
1186
1187   for (i = 0; i < G_N_ELEMENTS (empathy_preferences_tabs); i++)
1188     {
1189       if (!tp_strdiff (str, empathy_preferences_tabs[i]))
1190         return i;
1191     }
1192
1193   g_warn_if_reached ();
1194   return -1;
1195 }
1196
1197 const gchar *
1198 empathy_preferences_tab_to_string (EmpathyPreferencesTab tab)
1199 {
1200   g_return_val_if_fail (tab < G_N_ELEMENTS (empathy_preferences_tabs), NULL);
1201
1202   return empathy_preferences_tabs[tab];
1203 }
1204
1205 GtkWidget *
1206 empathy_preferences_new (GtkWindow *parent,
1207                          gboolean  shell_running)
1208 {
1209         GtkWidget              *self;
1210         EmpathyPreferencesPriv *priv;
1211         GtkWidget              *notif_page;
1212
1213         g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
1214
1215         self = g_object_new (EMPATHY_TYPE_PREFERENCES, NULL);
1216
1217         if (parent != NULL) {
1218                 gtk_window_set_transient_for (GTK_WINDOW (self),
1219                                               parent);
1220         }
1221
1222         /* when running in Gnome Shell we must hide these options since they
1223          * are meaningless in that context:
1224          * - 'Display incoming events in the notification area' (General->Behavior)
1225          * - 'Notifications' tab
1226          */
1227         priv = GET_PRIV (self);
1228         if (shell_running) {
1229                 gtk_widget_hide (priv->checkbutton_events_notif_area);
1230                 notif_page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (priv->notebook),
1231                                                         EMPATHY_PREFERENCES_TAB_NOTIFICATIONS);
1232                 gtk_widget_hide (notif_page);
1233         }
1234
1235         return self;
1236 }
1237
1238 void
1239 empathy_preferences_show_tab (EmpathyPreferences *self,
1240                               const gchar *page)
1241 {
1242         EmpathyPreferencesPriv *priv = GET_PRIV (self);
1243
1244         gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook),
1245                                        empathy_preferences_tab_from_string (page));
1246 }