9ce80eebbee651060cf865b302c36899635127fd
[empathy.git] / libempathy-gtk / empathy-spell-dialog.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 2004-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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include "config.h"
22
23 #include <string.h>
24
25 #include <glib/gi18n-lib.h>
26 #include <gtk/gtk.h>
27
28 #include <libempathy/empathy-utils.h>
29
30 #include "empathy-chat.h"
31 #include "empathy-spell.h"
32 #include "empathy-spell-dialog.h"
33 #include "empathy-ui-utils.h"
34
35 typedef struct {
36         GtkWidget   *window;
37         GtkWidget   *button_replace;
38         GtkWidget   *label_word;
39         GtkWidget   *treeview_words;
40
41         EmpathyChat  *chat;
42
43         gchar       *word;
44         GtkTextIter  start;
45         GtkTextIter  end;
46 } EmpathySpellDialog;
47
48 enum {
49         COL_SPELL_WORD,
50         COL_SPELL_COUNT
51 };
52
53 static void spell_dialog_model_populate_columns     (EmpathySpellDialog *dialog);
54 static void spell_dialog_model_populate_suggestions (EmpathySpellDialog *dialog);
55 static void spell_dialog_model_row_activated_cb     (GtkTreeView       *tree_view,
56                                                      GtkTreePath       *path,
57                                                      GtkTreeViewColumn *column,
58                                                      EmpathySpellDialog *dialog);
59 static void spell_dialog_model_selection_changed_cb (GtkTreeSelection  *treeselection,
60                                                      EmpathySpellDialog *dialog);
61 static void spell_dialog_model_setup                (EmpathySpellDialog *dialog);
62 static void spell_dialog_response_cb                (GtkWidget         *widget,
63                                                      gint               response,
64                                                      EmpathySpellDialog *dialog);
65 static void spell_dialog_destroy_cb                 (GtkWidget         *widget,
66                                                      EmpathySpellDialog *dialog);
67
68 static void
69 spell_dialog_model_populate_columns (EmpathySpellDialog *dialog)
70 {
71         GtkTreeModel      *model;
72         GtkTreeViewColumn *column;
73         GtkCellRenderer   *renderer;
74         guint              col_offset;
75
76         model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_words));
77
78         renderer = gtk_cell_renderer_text_new ();
79         col_offset = gtk_tree_view_insert_column_with_attributes (
80                 GTK_TREE_VIEW (dialog->treeview_words),
81                 -1, _("Word"),
82                 renderer,
83                 "text", COL_SPELL_WORD,
84                 NULL);
85
86         g_object_set_data (G_OBJECT (renderer),
87                            "column", GINT_TO_POINTER (COL_SPELL_WORD));
88
89         column = gtk_tree_view_get_column (GTK_TREE_VIEW (dialog->treeview_words), col_offset - 1);
90         gtk_tree_view_column_set_sort_column_id (column, COL_SPELL_WORD);
91         gtk_tree_view_column_set_resizable (column, FALSE);
92         gtk_tree_view_column_set_clickable (GTK_TREE_VIEW_COLUMN (column), TRUE);
93 }
94
95 static void
96 spell_dialog_model_populate_suggestions (EmpathySpellDialog *dialog)
97 {
98         GtkTreeModel *model;
99         GtkListStore *store;
100         GList        *suggestions, *l;
101
102         model = gtk_tree_view_get_model (GTK_TREE_VIEW (dialog->treeview_words));
103         store = GTK_LIST_STORE (model);
104
105         suggestions = empathy_spell_get_suggestions (dialog->word);
106         for (l = suggestions; l; l=l->next) {
107                 GtkTreeIter  iter;
108                 gchar       *word;
109
110                 word = l->data;
111
112                 gtk_list_store_append (store, &iter);
113                 gtk_list_store_set (store, &iter,
114                                     COL_SPELL_WORD, word,
115                                     -1);
116         }
117
118         empathy_spell_free_suggestions (suggestions);
119 }
120
121 static void
122 spell_dialog_model_row_activated_cb (GtkTreeView       *tree_view,
123                                GtkTreePath       *path,
124                                GtkTreeViewColumn *column,
125                                EmpathySpellDialog *dialog)
126 {
127         spell_dialog_response_cb (dialog->window, GTK_RESPONSE_OK, dialog);
128 }
129
130 static void
131 spell_dialog_model_selection_changed_cb (GtkTreeSelection  *treeselection,
132                                    EmpathySpellDialog *dialog)
133 {
134         gint count;
135
136         count = gtk_tree_selection_count_selected_rows (treeselection);
137         gtk_widget_set_sensitive (dialog->button_replace, (count == 1));
138 }
139
140 static void
141 spell_dialog_model_setup (EmpathySpellDialog *dialog)
142 {
143         GtkTreeView      *view;
144         GtkListStore     *store;
145         GtkTreeSelection *selection;
146
147         view = GTK_TREE_VIEW (dialog->treeview_words);
148
149         g_signal_connect (view, "row-activated",
150                           G_CALLBACK (spell_dialog_model_row_activated_cb),
151                           dialog);
152
153         store = gtk_list_store_new (COL_SPELL_COUNT,
154                                     G_TYPE_STRING);   /* word */
155
156         gtk_tree_view_set_model (view, GTK_TREE_MODEL (store));
157
158         selection = gtk_tree_view_get_selection (view);
159         gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
160
161         g_signal_connect (selection, "changed",
162                           G_CALLBACK (spell_dialog_model_selection_changed_cb),
163                           dialog);
164
165         spell_dialog_model_populate_columns (dialog);
166         spell_dialog_model_populate_suggestions (dialog);
167
168         g_object_unref (store);
169 }
170
171 static void
172 spell_dialog_destroy_cb (GtkWidget         *widget,
173                          EmpathySpellDialog *dialog)
174 {
175         g_object_unref (dialog->chat);
176         g_free (dialog->word);
177
178         g_free (dialog);
179 }
180
181 static void
182 spell_dialog_response_cb (GtkWidget         *widget,
183                           gint               response,
184                           EmpathySpellDialog *dialog)
185 {
186         if (response == GTK_RESPONSE_OK) {
187                 GtkTreeView      *view;
188                 GtkTreeModel     *model;
189                 GtkTreeSelection *selection;
190                 GtkTreeIter       iter;
191
192                 gchar            *new_word;
193
194                 view = GTK_TREE_VIEW (dialog->treeview_words);
195                 selection = gtk_tree_view_get_selection (view);
196
197                 if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
198                         return;
199                 }
200
201                 gtk_tree_model_get (model, &iter, COL_SPELL_WORD, &new_word, -1);
202
203                 empathy_chat_correct_word (dialog->chat,
204                                           &dialog->start,
205                                           &dialog->end,
206                                           new_word);
207
208                 g_free (new_word);
209         }
210
211         gtk_widget_destroy (dialog->window);
212 }
213
214 void
215 empathy_spell_dialog_show (EmpathyChat  *chat,
216                           GtkTextIter *start,
217                           GtkTextIter *end,
218                           const gchar *word)
219 {
220         EmpathySpellDialog *dialog;
221         GtkBuilder         *gui;
222         gchar              *str;
223         gchar              *filename;
224
225         g_return_if_fail (chat != NULL);
226         g_return_if_fail (word != NULL);
227
228         dialog = g_new0 (EmpathySpellDialog, 1);
229
230         dialog->chat = g_object_ref (chat);
231
232         dialog->word = g_strdup (word);
233
234         dialog->start = *start;
235         dialog->end = *end;
236
237         filename = empathy_file_lookup ("empathy-spell-dialog.ui",
238                                         "libempathy-gtk");
239         gui = empathy_builder_get_file (filename,
240                                      "spell_dialog", &dialog->window,
241                                      "button_replace", &dialog->button_replace,
242                                      "label_word", &dialog->label_word,
243                                      "treeview_words", &dialog->treeview_words,
244                                      NULL);
245         g_free (filename);
246
247         empathy_builder_connect (gui, dialog,
248                               "spell_dialog", "response", spell_dialog_response_cb,
249                               "spell_dialog", "destroy", spell_dialog_destroy_cb,
250                               NULL);
251
252         g_object_unref (gui);
253
254         str = g_markup_printf_escaped ("%s:\n<b>%s</b>",
255                                _("Suggestions for the word"),
256                                word);
257
258         gtk_label_set_markup (GTK_LABEL (dialog->label_word), str);
259         g_free (str);
260
261         spell_dialog_model_setup (dialog);
262
263         gtk_widget_show (dialog->window);
264 }