Updated Esperanto translation
[gtkhtml.git] / components / editor / gtkhtml-spell-dialog.c
blobc847f6bce239562aecab9ab0842b32930dac2485
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* gtkhtml-editor-spell-dialog.c
4 * Copyright (C) 2008 Novell, Inc.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of version 2 of the GNU Lesser General Public
8 * License as published by the Free Software Foundation.
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.
15 * You should have received a copy of the GNU Lesser 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.
21 #include "gtkhtml-spell-dialog.h"
23 #include <glib/gi18n-lib.h>
24 #include "gtkhtml-spell-checker.h"
26 enum {
27 COMBO_COLUMN_CHECKER, /* GTKHTML_TYPE_SPELL_CHECKER */
28 COMBO_COLUMN_TEXT /* G_TYPE_STRING */
31 enum {
32 PROP_0,
33 PROP_WORD
36 enum {
37 ADDED,
38 IGNORED,
39 NEXT_WORD,
40 PREV_WORD,
41 REPLACE,
42 REPLACE_ALL,
43 LAST_SIGNAL
46 struct _GtkhtmlSpellDialogPrivate {
48 /* widgets */
49 GtkWidget *add_word_button;
50 GtkWidget *back_button;
51 GtkWidget *dictionary_combo;
52 GtkWidget *ignore_button;
53 GtkWidget *replace_button;
54 GtkWidget *replace_all_button;
55 GtkWidget *skip_button;
56 GtkWidget *suggestion_label;
57 GtkWidget *tree_view;
59 GList *spell_checkers;
60 gchar *word;
63 static gpointer parent_class;
64 static guint signals[LAST_SIGNAL];
66 static void
67 spell_dialog_render_checker (GtkComboBox *combo_box,
68 GtkCellRenderer *renderer,
69 GtkTreeModel *model,
70 GtkTreeIter *iter)
72 const GtkhtmlSpellLanguage *language;
73 GtkhtmlSpellChecker *checker;
74 const gchar *name;
76 gtk_tree_model_get (model, iter, 0, &checker, -1);
77 language = gtkhtml_spell_checker_get_language (checker);
78 name = gtkhtml_spell_language_get_name (language);
80 g_object_set (renderer, "text", name, NULL);
82 g_object_unref (checker);
85 static void
86 spell_dialog_update_buttons (GtkhtmlSpellDialog *dialog)
88 gboolean sensitive;
90 /* Update "Add Word" and "Ignore" button sensitivity. */
91 sensitive = (gtkhtml_spell_dialog_get_word (dialog) != NULL);
92 gtk_widget_set_sensitive (dialog->priv->add_word_button, sensitive);
93 gtk_widget_set_sensitive (dialog->priv->ignore_button, sensitive);
96 static void
97 spell_dialog_update_suggestion_label (GtkhtmlSpellDialog *dialog)
99 GtkLabel *label;
100 const gchar *word;
101 gchar *markup;
102 gchar *text;
104 label = GTK_LABEL (dialog->priv->suggestion_label);
105 word = gtkhtml_spell_dialog_get_word (dialog);
107 /* Handle the simple case and get out. */
108 if (word == NULL) {
109 gtk_label_set_markup (label, NULL);
110 return;
113 text = g_strdup_printf (_("Suggestions for \"%s\""), word);
114 markup = g_strdup_printf ("<b>%s</b>", text);
116 gtk_label_set_markup (label, markup);
118 g_free (markup);
119 g_free (text);
122 static void
123 spell_dialog_update_tree_view (GtkhtmlSpellDialog *dialog)
125 GtkhtmlSpellChecker *checker;
126 GtkTreeSelection *selection;
127 GtkTreeView *tree_view;
128 GtkListStore *store;
129 GtkTreePath *path;
130 const gchar *word;
131 GList *list = NULL;
133 tree_view = GTK_TREE_VIEW (dialog->priv->tree_view);
134 selection = gtk_tree_view_get_selection (tree_view);
135 checker = gtkhtml_spell_dialog_get_active_checker (dialog);
136 word = gtkhtml_spell_dialog_get_word (dialog);
138 store = gtk_list_store_new (1, G_TYPE_STRING);
140 if (checker != NULL && word != NULL)
141 list = gtkhtml_spell_checker_get_suggestions (
142 checker, word, -1);
144 while (list != NULL) {
145 const gchar *suggestion = list->data;
146 GtkTreeIter iter;
148 gtk_list_store_append (store, &iter);
149 gtk_list_store_set (store, &iter, 0, suggestion, -1);
151 g_free (list->data);
152 list = g_list_delete_link (list, list);
155 gtk_tree_view_set_model (tree_view, GTK_TREE_MODEL (store));
157 /* Select the first item. */
158 path = gtk_tree_path_new_first ();
159 gtk_tree_selection_select_path (selection, path);
160 gtk_tree_path_free (path);
162 g_object_unref (checker);
165 static void
166 spell_dialog_add_word_cb (GtkhtmlSpellDialog *dialog)
168 GtkhtmlSpellChecker *checker;
169 const gchar *word;
171 checker = gtkhtml_spell_dialog_get_active_checker (dialog);
172 word = gtkhtml_spell_dialog_get_word (dialog);
174 gtkhtml_spell_checker_add_word (checker, word, -1);
175 g_signal_emit (dialog, signals[ADDED], 0);
177 gtkhtml_spell_dialog_next_word (dialog);
180 static void
181 spell_dialog_ignore_cb (GtkhtmlSpellDialog *dialog)
183 GtkhtmlSpellChecker *checker;
184 const gchar *word;
186 checker = gtkhtml_spell_dialog_get_active_checker (dialog);
187 word = gtkhtml_spell_dialog_get_word (dialog);
189 gtkhtml_spell_checker_add_word_to_session (checker, word, -1);
190 g_signal_emit (dialog, signals[IGNORED], 0);
192 gtkhtml_spell_dialog_next_word (dialog);
195 static void
196 spell_dialog_selection_changed_cb (GtkhtmlSpellDialog *dialog)
198 GtkTreeSelection *selection;
199 GtkTreeView *tree_view;
200 gboolean selected;
202 tree_view = GTK_TREE_VIEW (dialog->priv->tree_view);
203 selection = gtk_tree_view_get_selection (tree_view);
205 /* Update "Replace" and "Replace All" button sensitivity. */
206 selected = gtk_tree_selection_get_selected (selection, NULL, NULL);
207 gtk_widget_set_sensitive (dialog->priv->replace_button, selected);
208 gtk_widget_set_sensitive (dialog->priv->replace_all_button, selected);
211 static void
212 spell_dialog_replace_cb (GtkhtmlSpellDialog *dialog)
214 gchar *word;
216 word = gtkhtml_spell_dialog_get_active_suggestion (dialog);
217 g_return_if_fail (word != NULL);
219 g_signal_emit (dialog, signals[REPLACE], 0, word);
221 g_free (word);
224 static void
225 spell_dialog_replace_all_cb (GtkhtmlSpellDialog *dialog)
227 gchar *word;
229 word = gtkhtml_spell_dialog_get_active_suggestion (dialog);
230 g_return_if_fail (word != NULL);
232 g_signal_emit (dialog, signals[REPLACE_ALL], 0, word);
234 g_free (word);
237 static void
238 spell_dialog_set_property (GObject *object,
239 guint property_id,
240 const GValue *value,
241 GParamSpec *pspec)
243 switch (property_id) {
244 case PROP_WORD:
245 gtkhtml_spell_dialog_set_word (
246 GTKHTML_SPELL_DIALOG (object),
247 g_value_get_string (value));
248 return;
251 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
254 static void
255 spell_dialog_get_property (GObject *object,
256 guint property_id,
257 GValue *value,
258 GParamSpec *pspec)
260 switch (property_id) {
261 case PROP_WORD:
262 g_value_set_string (
263 value, gtkhtml_spell_dialog_get_word (
264 GTKHTML_SPELL_DIALOG (object)));
265 return;
268 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
271 static void
272 spell_dialog_dispose (GObject *object)
274 GtkhtmlSpellDialogPrivate *priv;
276 priv = GTKHTML_SPELL_DIALOG (object)->priv;
278 if (priv->add_word_button != NULL) {
279 g_object_unref (priv->add_word_button);
280 priv->add_word_button = NULL;
283 if (priv->back_button != NULL) {
284 g_object_unref (priv->back_button);
285 priv->back_button = NULL;
288 if (priv->dictionary_combo != NULL) {
289 g_object_unref (priv->dictionary_combo);
290 priv->dictionary_combo = NULL;
293 if (priv->ignore_button != NULL) {
294 g_object_unref (priv->ignore_button);
295 priv->ignore_button = NULL;
298 if (priv->replace_button != NULL) {
299 g_object_unref (priv->replace_button);
300 priv->replace_button = NULL;
303 if (priv->replace_all_button != NULL) {
304 g_object_unref (priv->replace_all_button);
305 priv->replace_all_button = NULL;
308 if (priv->skip_button != NULL) {
309 g_object_unref (priv->skip_button);
310 priv->skip_button = NULL;
313 if (priv->tree_view != NULL) {
314 g_object_unref (priv->tree_view);
315 priv->tree_view = NULL;
318 /* Chain up to parent's dispose() method. */
319 G_OBJECT_CLASS (parent_class)->dispose (object);
322 static void
323 spell_dialog_finalize (GObject *object)
325 GtkhtmlSpellDialogPrivate *priv;
327 priv = GTKHTML_SPELL_DIALOG (object)->priv;
329 g_free (priv->word);
331 /* Chain up to parent's finalize() method. */
332 G_OBJECT_CLASS (parent_class)->finalize (object);
335 static void
336 spell_dialog_class_init (GtkhtmlSpellDialogClass *class)
338 GObjectClass *object_class;
340 parent_class = g_type_class_peek_parent (class);
341 g_type_class_add_private (class, sizeof (GtkhtmlSpellDialogPrivate));
343 object_class = G_OBJECT_CLASS (class);
344 object_class->set_property = spell_dialog_set_property;
345 object_class->get_property = spell_dialog_get_property;
346 object_class->dispose = spell_dialog_dispose;
347 object_class->finalize = spell_dialog_finalize;
349 g_object_class_install_property (
350 object_class,
351 PROP_WORD,
352 g_param_spec_string (
353 "word",
354 "Misspelled Word",
355 "The current misspelled word",
356 NULL,
357 G_PARAM_READWRITE));
359 signals[ADDED] = g_signal_new (
360 "added",
361 G_OBJECT_CLASS_TYPE (object_class),
362 G_SIGNAL_RUN_LAST,
363 0, NULL, NULL,
364 g_cclosure_marshal_VOID__VOID,
365 G_TYPE_NONE, 0);
367 signals[IGNORED] = g_signal_new (
368 "ignored",
369 G_OBJECT_CLASS_TYPE (object_class),
370 G_SIGNAL_RUN_LAST,
371 0, NULL, NULL,
372 g_cclosure_marshal_VOID__VOID,
373 G_TYPE_NONE, 0);
375 signals[NEXT_WORD] = g_signal_new (
376 "next-word",
377 G_OBJECT_CLASS_TYPE (object_class),
378 G_SIGNAL_RUN_LAST,
379 0, NULL, NULL,
380 g_cclosure_marshal_VOID__VOID,
381 G_TYPE_NONE, 0);
383 signals[PREV_WORD] = g_signal_new (
384 "prev-word",
385 G_OBJECT_CLASS_TYPE (object_class),
386 G_SIGNAL_RUN_LAST,
387 0, NULL, NULL,
388 g_cclosure_marshal_VOID__VOID,
389 G_TYPE_NONE, 0);
391 signals[REPLACE] = g_signal_new (
392 "replace",
393 G_OBJECT_CLASS_TYPE (object_class),
394 G_SIGNAL_RUN_LAST,
395 0, NULL, NULL,
396 g_cclosure_marshal_VOID__STRING,
397 G_TYPE_NONE, 1,
398 G_TYPE_STRING);
400 signals[REPLACE_ALL] = g_signal_new (
401 "replace-all",
402 G_OBJECT_CLASS_TYPE (object_class),
403 G_SIGNAL_RUN_LAST,
404 0, NULL, NULL,
405 g_cclosure_marshal_VOID__STRING,
406 G_TYPE_NONE, 1,
407 G_TYPE_STRING);
410 static void
411 spell_dialog_init (GtkhtmlSpellDialog *dialog)
413 GtkTreeSelection *selection;
414 GtkTreeViewColumn *column;
415 GtkCellRenderer *renderer;
416 GtkWidget *container;
417 GtkWidget *content_area;
418 GtkWidget *table;
419 GtkWidget *widget;
420 gchar *markup;
422 dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE (
423 dialog, GTKHTML_TYPE_SPELL_DIALOG, GtkhtmlSpellDialogPrivate);
425 g_signal_connect (
426 dialog, "notify::word", G_CALLBACK (
427 spell_dialog_update_buttons), NULL);
429 g_signal_connect (
430 dialog, "notify::word", G_CALLBACK (
431 spell_dialog_update_suggestion_label), NULL);
433 g_signal_connect (
434 dialog, "notify::word", G_CALLBACK (
435 spell_dialog_update_tree_view), NULL);
437 /* Build the widgets. */
439 content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
441 gtk_dialog_add_button (
442 GTK_DIALOG (dialog), GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
443 gtk_window_set_title (GTK_WINDOW (dialog), _("Spell Checker"));
444 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
446 gtk_box_set_spacing (GTK_BOX (content_area), 2);
448 /* Table */
449 widget = gtk_table_new (4, 2, FALSE);
450 gtk_container_set_border_width (GTK_CONTAINER (widget), 5);
451 gtk_table_set_row_spacings (GTK_TABLE (widget), 6);
452 gtk_table_set_col_spacings (GTK_TABLE (widget), 6);
453 gtk_table_set_row_spacing (GTK_TABLE (widget), 1, 12);
454 gtk_box_pack_start (GTK_BOX (content_area), widget, TRUE, TRUE, 0);
455 gtk_widget_show (widget);
456 table = widget;
458 /* Suggestion Label */
459 widget = gtk_label_new (NULL);
460 gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END);
461 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
462 gtk_table_attach (
463 GTK_TABLE (table), widget, 0, 2, 0, 1,
464 GTK_EXPAND | GTK_FILL, 0, 0, 0);
465 dialog->priv->suggestion_label = g_object_ref (widget);
466 gtk_widget_show (widget);
468 /* Scrolled Window */
469 widget = gtk_scrolled_window_new (NULL, NULL);
470 gtk_scrolled_window_set_policy (
471 GTK_SCROLLED_WINDOW (widget),
472 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
473 gtk_scrolled_window_set_shadow_type (
474 GTK_SCROLLED_WINDOW (widget),
475 GTK_SHADOW_ETCHED_IN);
476 gtk_table_attach (
477 GTK_TABLE (table), widget, 0, 1, 1, 2,
478 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
479 gtk_widget_show (widget);
480 container = widget;
482 /* Tree View */
483 widget = gtk_tree_view_new ();
484 column = gtk_tree_view_column_new ();
485 renderer = gtk_cell_renderer_text_new ();
486 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
487 g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
488 gtk_tree_view_column_pack_start (column, renderer, TRUE);
489 gtk_tree_view_column_add_attribute (column, renderer, "text", 0);
490 gtk_tree_view_append_column (GTK_TREE_VIEW (widget), column);
491 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (widget), FALSE);
492 gtk_label_set_mnemonic_widget (
493 GTK_LABEL (dialog->priv->suggestion_label), widget);
494 g_signal_connect_swapped (
495 widget, "row-activated",
496 G_CALLBACK (spell_dialog_replace_cb), dialog);
497 g_signal_connect_swapped (
498 selection, "changed",
499 G_CALLBACK (spell_dialog_selection_changed_cb), dialog);
500 gtk_container_add (GTK_CONTAINER (container), widget);
501 dialog->priv->tree_view = g_object_ref (widget);
502 gtk_widget_show (widget);
504 /* Vertical Button Box */
505 widget = gtk_vbutton_box_new ();
506 gtk_button_box_set_layout (
507 GTK_BUTTON_BOX (widget), GTK_BUTTONBOX_START);
508 gtk_box_set_spacing (GTK_BOX (widget), 6);
509 gtk_table_attach (
510 GTK_TABLE (table), widget, 1, 2, 1, 2,
511 0, GTK_EXPAND | GTK_FILL, 0, 0);
512 gtk_widget_show (widget);
513 container = widget;
515 /* Replace Button */
516 widget = gtk_button_new_with_mnemonic (_("_Replace"));
517 gtk_button_set_image (
518 GTK_BUTTON (widget),
519 gtk_image_new_from_stock (
520 GTK_STOCK_CONVERT, GTK_ICON_SIZE_BUTTON));
521 g_signal_connect_swapped (
522 widget, "clicked",
523 G_CALLBACK (spell_dialog_replace_cb), dialog);
524 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
525 dialog->priv->replace_button = g_object_ref (widget);
526 gtk_widget_set_sensitive (widget, FALSE);
527 gtk_widget_show (widget);
529 /* Replace All Button */
530 widget = gtk_button_new_with_mnemonic (_("R_eplace All"));
531 gtk_button_set_image (
532 GTK_BUTTON (widget),
533 gtk_image_new_from_stock (
534 GTK_STOCK_APPLY, GTK_ICON_SIZE_BUTTON));
535 g_signal_connect_swapped (
536 widget, "clicked",
537 G_CALLBACK (spell_dialog_replace_all_cb), dialog);
538 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
539 dialog->priv->replace_all_button = g_object_ref (widget);
540 gtk_widget_set_sensitive (widget, FALSE);
541 gtk_widget_show (widget);
543 /* Ignore Button */
544 widget = gtk_button_new_with_mnemonic (_("_Ignore"));
545 gtk_button_set_image (
546 GTK_BUTTON (widget),
547 gtk_image_new_from_stock (
548 GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON));
549 g_signal_connect_swapped (
550 widget, "clicked",
551 G_CALLBACK (spell_dialog_ignore_cb), dialog);
552 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
553 dialog->priv->ignore_button = g_object_ref (widget);
554 gtk_widget_set_sensitive (widget, FALSE);
555 gtk_widget_show (widget);
557 /* Skip Button */
558 widget = gtk_button_new_with_mnemonic (_("_Skip"));
559 gtk_button_set_image (
560 GTK_BUTTON (widget),
561 gtk_image_new_from_stock (
562 GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON));
563 g_signal_connect_swapped (
564 widget, "clicked",
565 G_CALLBACK (gtkhtml_spell_dialog_next_word), dialog);
566 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
567 dialog->priv->skip_button = g_object_ref (widget);
568 gtk_widget_show (widget);
570 /* Back Button */
571 widget = gtk_button_new_with_mnemonic (_("_Back"));
572 gtk_button_set_image (
573 GTK_BUTTON (widget),
574 gtk_image_new_from_stock (
575 GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON));
576 g_signal_connect_swapped (
577 widget, "clicked",
578 G_CALLBACK (gtkhtml_spell_dialog_prev_word), dialog);
579 gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0);
580 dialog->priv->back_button = g_object_ref (widget);
581 gtk_widget_show (widget);
583 /* Dictionary Label */
584 markup = g_markup_printf_escaped ("<b>%s</b>", _("Dictionary"));
585 widget = gtk_label_new (markup);
586 gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
587 gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
588 gtk_table_attach (
589 GTK_TABLE (table), widget, 0, 2, 2, 3,
590 GTK_EXPAND | GTK_FILL, 0, 0, 0);
591 gtk_widget_show (widget);
592 g_free (markup);
594 /* Dictionary Combo Box */
595 widget = gtk_combo_box_new ();
596 renderer = gtk_cell_renderer_text_new ();
597 gtk_cell_layout_pack_start (
598 GTK_CELL_LAYOUT (widget), renderer, TRUE);
599 gtk_cell_layout_set_cell_data_func (
600 GTK_CELL_LAYOUT (widget), renderer,
601 (GtkCellLayoutDataFunc) spell_dialog_render_checker,
602 NULL, NULL);
603 g_signal_connect_swapped (
604 widget, "changed",
605 G_CALLBACK (spell_dialog_update_tree_view), dialog);
606 gtk_table_attach (
607 GTK_TABLE (table), widget, 0, 1, 3, 4,
608 GTK_EXPAND | GTK_FILL, 0, 0, 0);
609 dialog->priv->dictionary_combo = g_object_ref (widget);
610 gtk_widget_show (widget);
612 /* Add Word Button */
613 widget = gtk_button_new_with_mnemonic (_("_Add Word"));
614 g_signal_connect_swapped (
615 widget, "clicked",
616 G_CALLBACK (spell_dialog_add_word_cb), dialog);
617 gtk_button_set_image (
618 GTK_BUTTON (widget),
619 gtk_image_new_from_stock (
620 GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON));
621 gtk_table_attach (
622 GTK_TABLE (table), widget, 1, 2, 3, 4,
623 GTK_FILL, 0, 0, 0);
624 dialog->priv->add_word_button = g_object_ref (widget);
625 gtk_widget_show (widget);
628 GType
629 gtkhtml_spell_dialog_get_type (void)
631 static GType type = 0;
633 if (G_UNLIKELY (type == 0)) {
634 static const GTypeInfo type_info = {
635 sizeof (GtkhtmlSpellDialogClass),
636 (GBaseInitFunc) NULL,
637 (GBaseFinalizeFunc) NULL,
638 (GClassInitFunc) spell_dialog_class_init,
639 (GClassFinalizeFunc) NULL,
640 NULL, /* class_data */
641 sizeof (GtkhtmlSpellDialog),
642 0, /* n_preallocs */
643 (GInstanceInitFunc) spell_dialog_init,
644 NULL /* value_table */
647 type = g_type_register_static (
648 GTK_TYPE_DIALOG, "GtkhtmlSpellDialog", &type_info, 0);
651 return type;
654 GtkWidget *
655 gtkhtml_spell_dialog_new (GtkWindow *parent)
657 return g_object_new (
658 GTKHTML_TYPE_SPELL_DIALOG, "transient-for", parent, NULL);
661 void
662 gtkhtml_spell_dialog_close (GtkhtmlSpellDialog *dialog)
664 g_return_if_fail (GTKHTML_IS_SPELL_DIALOG (dialog));
666 gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
669 const gchar *
670 gtkhtml_spell_dialog_get_word (GtkhtmlSpellDialog *dialog)
672 g_return_val_if_fail (GTKHTML_IS_SPELL_DIALOG (dialog), NULL);
674 return dialog->priv->word;
677 void
678 gtkhtml_spell_dialog_set_word (GtkhtmlSpellDialog *dialog,
679 const gchar *word)
681 g_return_if_fail (GTKHTML_IS_SPELL_DIALOG (dialog));
683 /* Do not emit signals if the word is unchanged. */
684 if (word != NULL && dialog->priv->word != NULL)
685 if (g_str_equal (word, dialog->priv->word))
686 return;
688 g_free (dialog->priv->word);
689 dialog->priv->word = g_strdup (word);
691 g_object_notify (G_OBJECT (dialog), "word");
694 void
695 gtkhtml_spell_dialog_next_word (GtkhtmlSpellDialog *dialog)
697 g_signal_emit (dialog, signals[NEXT_WORD], 0);
700 void
701 gtkhtml_spell_dialog_prev_word (GtkhtmlSpellDialog *dialog)
703 g_signal_emit (dialog, signals[PREV_WORD], 0);
706 GList *
707 gtkhtml_spell_dialog_get_spell_checkers (GtkhtmlSpellDialog *dialog)
709 g_return_val_if_fail (GTKHTML_IS_SPELL_DIALOG (dialog), NULL);
711 return g_list_copy (dialog->priv->spell_checkers);
714 void
715 gtkhtml_spell_dialog_set_spell_checkers (GtkhtmlSpellDialog *dialog,
716 GList *spell_checkers)
718 GtkComboBox *combo_box;
719 GtkListStore *store;
720 GList *list;
722 g_return_if_fail (GTKHTML_IS_SPELL_DIALOG (dialog));
724 combo_box = GTK_COMBO_BOX (dialog->priv->dictionary_combo);
726 /* Free the old list of spell checkers. */
727 list = dialog->priv->spell_checkers;
728 g_list_foreach (list, (GFunc) g_object_unref, NULL);
729 g_list_free (list);
731 /* Copy and sort the new list of spell checkers. */
732 list = g_list_sort (
733 g_list_copy (spell_checkers),
734 (GCompareFunc) gtkhtml_spell_checker_compare);
735 g_list_foreach (list, (GFunc) g_object_ref, NULL);
736 dialog->priv->spell_checkers = list;
738 /* Populate a list store for the combo box. */
740 store = gtk_list_store_new (1, GTKHTML_TYPE_SPELL_CHECKER);
742 while (list != NULL) {
743 GtkhtmlSpellChecker *checker = list->data;
744 GtkTreeIter iter;
746 gtk_list_store_append (store, &iter);
747 gtk_list_store_set (store, &iter, 0, checker, -1);
749 list = g_list_next (list);
752 /* FIXME Try to preserve the previously selected language. */
753 gtk_combo_box_set_model (combo_box, GTK_TREE_MODEL (store));
754 gtk_combo_box_set_active (combo_box, 0);
756 g_object_unref (store);
758 /* XXX notify property? */
761 GtkhtmlSpellChecker *
762 gtkhtml_spell_dialog_get_active_checker (GtkhtmlSpellDialog *dialog)
764 GtkhtmlSpellChecker *checker;
765 GtkComboBox *combo_box;
766 GtkTreeModel *model;
767 GtkTreeIter iter;
769 g_return_val_if_fail (GTKHTML_IS_SPELL_DIALOG (dialog), NULL);
771 combo_box = GTK_COMBO_BOX (dialog->priv->dictionary_combo);
772 model = gtk_combo_box_get_model (combo_box);
774 if (!gtk_combo_box_get_active_iter (combo_box, &iter))
775 return NULL;
777 gtk_tree_model_get (model, &iter, COMBO_COLUMN_CHECKER, &checker, -1);
779 return checker;
782 gchar *
783 gtkhtml_spell_dialog_get_active_suggestion (GtkhtmlSpellDialog *dialog)
785 GtkTreeSelection *selection;
786 GtkTreeView *tree_view;
787 GtkTreeModel *model;
788 GtkTreeIter iter;
789 gchar *word;
791 g_return_val_if_fail (GTKHTML_IS_SPELL_DIALOG (dialog), NULL);
793 tree_view = GTK_TREE_VIEW (dialog->priv->tree_view);
794 selection = gtk_tree_view_get_selection (tree_view);
796 /* If nothing is selected, return NULL. */
797 if (!gtk_tree_selection_get_selected (selection, &model, &iter))
798 return NULL;
800 gtk_tree_model_get (model, &iter, 0, &word, -1);
801 g_return_val_if_fail (word != NULL, NULL);
803 return word;