]> git.0d.be Git - empathy.git/blob - libempathy-gtk/empathy-status-preset-dialog.c
a428667e914ecf11811f61e6a70003da28f12348
[empathy.git] / libempathy-gtk / empathy-status-preset-dialog.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * empathy-status-preset-dialog.c
4  *
5  * EmpathyStatusPresetDialog - a dialog for adding and removing preset status
6  * messages.
7  *
8  * Copyright (C) 2009 Collabora Ltd.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of the
13  * License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public
21  * License along with this program; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  *
25  * Authors: Davyd Madeley <davyd.madeley@collabora.co.uk>
26  */
27
28 #include "config.h"
29
30 #include <glib/gi18n-lib.h>
31 #include <gtk/gtk.h>
32
33 #include <libmissioncontrol/mc-enum-types.h>
34
35 #include <libempathy/empathy-utils.h>
36 #include <libempathy/empathy-status-presets.h>
37
38 #define DEBUG_FLAG EMPATHY_DEBUG_OTHER
39 #include <libempathy/empathy-debug.h>
40
41 #include "empathy-ui-utils.h"
42 #include "empathy-status-preset-dialog.h"
43
44 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyStatusPresetDialog)
45
46 G_DEFINE_TYPE (EmpathyStatusPresetDialog, empathy_status_preset_dialog, GTK_TYPE_DIALOG);
47
48 static McPresence states[] = {
49         MC_PRESENCE_AVAILABLE,
50         MC_PRESENCE_DO_NOT_DISTURB,
51         MC_PRESENCE_AWAY
52 };
53
54 typedef struct _EmpathyStatusPresetDialogPriv EmpathyStatusPresetDialogPriv;
55 struct _EmpathyStatusPresetDialogPriv
56 {
57         GtkWidget *presets_treeview;
58         GtkWidget *add_combobox;
59         GtkWidget *add_button;
60
61         McPresence selected_state;
62         gboolean add_combo_changed;
63 };
64
65 enum
66 {
67         PRESETS_STORE_STATE,
68         PRESETS_STORE_ICON_NAME,
69         PRESETS_STORE_STATUS,
70         PRESETS_STORE_N_COLS
71 };
72
73 enum
74 {
75         ADD_COMBO_STATE,
76         ADD_COMBO_ICON_NAME,
77         ADD_COMBO_STATUS,
78         ADD_COMBO_DEFAULT_TEXT,
79         ADD_COMBO_N_COLS
80 };
81
82 static void
83 empathy_status_preset_dialog_class_init (EmpathyStatusPresetDialogClass *class)
84 {
85         GObjectClass *gobject_class;
86
87         gobject_class = G_OBJECT_CLASS (class);
88
89         g_type_class_add_private (gobject_class,
90                         sizeof (EmpathyStatusPresetDialogPriv));
91 }
92
93 static void
94 status_preset_dialog_setup_presets_update (EmpathyStatusPresetDialog *self)
95 {
96         EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
97         GtkListStore *store;
98         int i;
99
100         store = GTK_LIST_STORE (gtk_tree_view_get_model (
101                                 GTK_TREE_VIEW (priv->presets_treeview)));
102
103         gtk_list_store_clear (store);
104
105         for (i = 0; i < G_N_ELEMENTS (states); i++) {
106                 GList *presets, *l;
107                 const char *icon_name;
108
109                 presets = empathy_status_presets_get (states[i], -1);
110                 icon_name = empathy_icon_name_for_presence (states[i]);
111
112                 for (l = presets; l; l = l->next) {
113                         char *preset = (char *) l->data;
114
115                         gtk_list_store_insert_with_values (store,
116                                         NULL, -1,
117                                         PRESETS_STORE_STATE, states[i],
118                                         PRESETS_STORE_ICON_NAME, icon_name,
119                                         PRESETS_STORE_STATUS, preset,
120                                         -1);
121                 }
122
123                 g_list_free (presets);
124         }
125 }
126
127 static void
128 status_preset_add_combo_reset (EmpathyStatusPresetDialog *self)
129 {
130         EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
131
132         gtk_combo_box_set_active (GTK_COMBO_BOX (priv->add_combobox), 0);
133 }
134
135 static void
136 status_preset_dialog_setup_add_combobox (EmpathyStatusPresetDialog *self)
137 {
138         EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
139         GtkWidget *combobox = priv->add_combobox;
140         GtkListStore *store;
141         GtkCellRenderer *renderer;
142         int i;
143
144         store = gtk_list_store_new (ADD_COMBO_N_COLS,
145                         MC_TYPE_PRESENCE,       /* ADD_COMBO_STATE */
146                         G_TYPE_STRING,          /* ADD_COMBO_ICON_NAME */
147                         G_TYPE_STRING,          /* ADD_COMBO_STATUS */
148                         G_TYPE_STRING);         /* ADD_COMBO_DEFAULT_TEXT */
149
150         gtk_combo_box_set_model (GTK_COMBO_BOX (combobox),
151                                  GTK_TREE_MODEL (store));
152         g_object_unref (store);
153
154         gtk_combo_box_entry_set_text_column (GTK_COMBO_BOX_ENTRY (combobox),
155                         ADD_COMBO_DEFAULT_TEXT);
156
157         for (i = 0; i < G_N_ELEMENTS (states); i++) {
158                 gtk_list_store_insert_with_values (store, NULL, -1,
159                                 ADD_COMBO_STATE, states[i],
160                                 ADD_COMBO_ICON_NAME, empathy_icon_name_for_presence (states[i]),
161                                 ADD_COMBO_STATUS, empathy_presence_get_default_message (states[i]),
162                                 ADD_COMBO_DEFAULT_TEXT, _("Enter Custom Message"),
163                                 -1);
164         }
165
166         gtk_cell_layout_clear (GTK_CELL_LAYOUT (combobox));
167
168         renderer = gtk_cell_renderer_pixbuf_new ();
169         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, FALSE);
170         gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox), renderer,
171                         "icon-name", ADD_COMBO_ICON_NAME);
172
173         renderer = gtk_cell_renderer_text_new ();
174         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, TRUE);
175         gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combobox), renderer,
176                         "text", ADD_COMBO_STATUS);
177         g_object_set (renderer,
178                         "style", PANGO_STYLE_ITALIC,
179                         "foreground", "Gray", /* FIXME - theme */
180                         NULL);
181
182         status_preset_add_combo_reset (self);
183 }
184
185 static void
186 status_preset_dialog_setup_presets_treeview (EmpathyStatusPresetDialog *self)
187 {
188         EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
189         GtkWidget *treeview = priv->presets_treeview;
190         GtkListStore *store;
191         GtkTreeViewColumn *column;
192         GtkCellRenderer *renderer;
193
194         store = gtk_list_store_new (PRESETS_STORE_N_COLS,
195                         MC_TYPE_PRESENCE,       /* PRESETS_STORE_STATE */
196                         G_TYPE_STRING,          /* PRESETS_STORE_ICON_NAME */
197                         G_TYPE_STRING);         /* PRESETS_STORE_STATUS */
198
199         gtk_tree_view_set_model (GTK_TREE_VIEW (treeview),
200                                  GTK_TREE_MODEL (store));
201         g_object_unref (store);
202
203         status_preset_dialog_setup_presets_update (self);
204
205         column = gtk_tree_view_column_new ();
206         gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
207
208         renderer = gtk_cell_renderer_pixbuf_new ();
209         gtk_tree_view_column_pack_start (column, renderer, FALSE);
210         gtk_tree_view_column_add_attribute (column, renderer,
211                         "icon-name", PRESETS_STORE_ICON_NAME);
212
213         renderer = gtk_cell_renderer_text_new ();
214         gtk_tree_view_column_pack_start (column, renderer, TRUE);
215         gtk_tree_view_column_add_attribute (column, renderer,
216                         "text", PRESETS_STORE_STATUS);
217 }
218
219 static void
220 status_preset_dialog_preset_selection_changed (GtkTreeSelection *selection,
221                                                GtkWidget *remove_button)
222 {
223         /* update the sensitivity of the Remove button */
224         gtk_widget_set_sensitive (remove_button,
225                         gtk_tree_selection_get_selected (selection, NULL, NULL));
226 }
227
228 static void
229 status_preset_dialog_preset_remove (GtkButton *button,
230                                     EmpathyStatusPresetDialog *self)
231 {
232         EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
233         GtkTreeSelection *selection;
234         GtkTreeModel *model;
235         GtkTreeIter iter;
236         McPresence state;
237         char *status;
238
239         selection = gtk_tree_view_get_selection (
240                         GTK_TREE_VIEW (priv->presets_treeview));
241
242         g_return_if_fail (gtk_tree_selection_get_selected (selection,
243                                 &model, &iter));
244
245         gtk_tree_model_get (model, &iter,
246                         PRESETS_STORE_STATE, &state,
247                         PRESETS_STORE_STATUS, &status,
248                         -1);
249
250         DEBUG ("REMOVE PRESET (%i, %s)\n", state, status);
251         empathy_status_presets_remove (state, status);
252
253         g_free (status);
254
255         status_preset_dialog_setup_presets_update (self);
256 }
257
258 static void
259 status_preset_dialog_add_combo_changed (GtkComboBox *combo,
260                                         EmpathyStatusPresetDialog *self)
261 {
262         EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
263         GtkWidget *entry;
264         GtkTreeModel *model;
265         GtkTreeIter iter;
266
267         model = gtk_combo_box_get_model (combo);
268         entry = gtk_bin_get_child (GTK_BIN (combo));
269
270         if (gtk_combo_box_get_active_iter (combo, &iter)) {
271                 char *icon_name;
272                 GdkColor colour;
273
274                 gtk_tree_model_get (model, &iter,
275                                 PRESETS_STORE_STATE, &priv->selected_state,
276                                 PRESETS_STORE_ICON_NAME, &icon_name,
277                                 -1);
278
279                 gtk_entry_set_icon_from_icon_name (GTK_ENTRY (entry),
280                                 GTK_ENTRY_ICON_PRIMARY,
281                                 icon_name);
282
283                 g_free (icon_name);
284
285                 gtk_widget_grab_focus (entry);
286                 gtk_editable_select_region (GTK_EDITABLE (entry), 0, -1);
287
288                 priv->add_combo_changed = FALSE;
289                 gtk_widget_set_sensitive (priv->add_button, FALSE);
290
291                 gdk_color_parse ("Gray", &colour); /* FIXME - theme */
292                 gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &colour);
293         } else {
294                 priv->add_combo_changed = TRUE;
295                 gtk_widget_set_sensitive (priv->add_button, TRUE);
296                 gtk_widget_modify_text (entry, GTK_STATE_NORMAL, NULL);
297         }
298 }
299
300 static void
301 status_preset_dialog_add_preset (GtkWidget *widget,
302                                  EmpathyStatusPresetDialog *self)
303 {
304         EmpathyStatusPresetDialogPriv *priv = GET_PRIV (self);
305         GtkWidget *entry;
306         const char *status;
307
308         g_return_if_fail (priv->add_combo_changed);
309
310         entry = gtk_bin_get_child (GTK_BIN (priv->add_combobox));
311         status = gtk_entry_get_text (GTK_ENTRY (entry));
312
313         DEBUG ("ADD PRESET (%i, %s)\n", priv->selected_state, status);
314         empathy_status_presets_set_last (priv->selected_state, status);
315
316         status_preset_dialog_setup_presets_update (self);
317         status_preset_add_combo_reset (self);
318 }
319
320 static void
321 empathy_status_preset_dialog_init (EmpathyStatusPresetDialog *self)
322 {
323         EmpathyStatusPresetDialogPriv *priv = self->priv =
324                 G_TYPE_INSTANCE_GET_PRIVATE (self,
325                         EMPATHY_TYPE_STATUS_PRESET_DIALOG,
326                         EmpathyStatusPresetDialogPriv);
327         GtkBuilder *gui;
328         GtkWidget *toplevel_vbox, *remove_button;
329         char *filename;
330
331         gtk_window_set_title (GTK_WINDOW (self),
332                         _("Edit Custom Messages"));
333         gtk_dialog_set_has_separator (GTK_DIALOG (self), FALSE);
334         gtk_dialog_add_button (GTK_DIALOG (self),
335                         GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
336
337         filename = empathy_file_lookup ("empathy-status-preset-dialog.ui",
338                         "libempathy-gtk");
339         gui = empathy_builder_get_file (filename,
340                         "toplevel-vbox", &toplevel_vbox,
341                         "presets-treeview", &priv->presets_treeview,
342                         "remove-button", &remove_button,
343                         "add-combobox", &priv->add_combobox,
344                         "add-button", &priv->add_button,
345                         NULL);
346         g_free (filename);
347
348         g_signal_connect (gtk_tree_view_get_selection (
349                                 GTK_TREE_VIEW (priv->presets_treeview)),
350                         "changed",
351                         G_CALLBACK (status_preset_dialog_preset_selection_changed),
352                         remove_button);
353
354         g_signal_connect (gtk_bin_get_child (GTK_BIN (priv->add_combobox)),
355                         "activate",
356                         G_CALLBACK (status_preset_dialog_add_preset),
357                         self);
358
359         empathy_builder_connect (gui, self,
360                         "remove-button", "clicked", status_preset_dialog_preset_remove,
361                         "add-combobox", "changed", status_preset_dialog_add_combo_changed,
362                         "add-button", "clicked", status_preset_dialog_add_preset,
363                         NULL);
364
365         status_preset_dialog_setup_presets_treeview (self);
366         status_preset_dialog_setup_add_combobox (self);
367
368         gtk_box_pack_start(GTK_BOX (GTK_DIALOG (self)->vbox), toplevel_vbox,
369                         TRUE, TRUE, 0);
370
371         g_object_unref (gui);
372 }
373
374 GtkWidget *
375 empathy_status_preset_dialog_new (GtkWindow *parent)
376 {
377         GtkWidget *self = g_object_new (EMPATHY_TYPE_STATUS_PRESET_DIALOG,
378                         NULL);
379
380         if (parent) {
381                 gtk_window_set_transient_for (GTK_WINDOW (self), parent);
382         }
383
384         return self;
385 }