Updated Hungarian translation
[evolution.git] / e-util / e-html-editor-actions.c
blob7ebcef1ade13c310ea669549d9a54c1e704eedbb
1 /* e-html-editor-actions.c
3 * Copyright (C) 2012 Dan Vrátil <dvratil@redhat.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of version 2 of the GNU Lesser General Public
7 * License as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <gio/gio.h>
25 #include <glib/gi18n-lib.h>
26 #include <string.h>
27 #include <enchant/enchant.h>
29 #include "e-html-editor.h"
30 #include "e-html-editor-private.h"
31 #include "e-html-editor-actions.h"
32 #include "e-html-editor-utils.h"
33 #include "e-emoticon-action.h"
34 #include "e-emoticon-chooser.h"
35 #include "e-image-chooser-dialog.h"
36 #include "e-spell-checker.h"
37 #include "e-misc-utils.h"
39 static void
40 insert_html_file_ready_cb (GFile *file,
41 GAsyncResult *result,
42 EHTMLEditor *editor)
44 EHTMLEditorSelection *selection;
45 gchar *contents = NULL;
46 gsize length;
47 GError *error = NULL;
49 g_file_load_contents_finish (
50 file, result, &contents, &length, NULL, &error);
51 if (error != NULL) {
52 GtkWidget *dialog;
54 dialog = gtk_message_dialog_new (
55 GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (editor))),
56 0, GTK_MESSAGE_ERROR,
57 GTK_BUTTONS_CLOSE, _("Failed to insert HTML file."));
58 gtk_message_dialog_format_secondary_text (
59 GTK_MESSAGE_DIALOG (dialog), "%s.", error->message);
60 gtk_dialog_run (GTK_DIALOG (dialog));
61 gtk_widget_destroy (dialog);
63 g_clear_error (&error);
64 g_object_unref (editor);
65 return;
68 selection = e_html_editor_view_get_selection (
69 e_html_editor_get_view (editor));
70 e_html_editor_selection_insert_html (selection, contents);
71 g_free (contents);
73 g_object_unref (editor);
76 static void
77 insert_text_file_ready_cb (GFile *file,
78 GAsyncResult *result,
79 EHTMLEditor *editor)
81 EHTMLEditorSelection *selection;
82 gchar *contents;
83 gsize length;
84 GError *error = NULL;
86 g_file_load_contents_finish (
87 file, result, &contents, &length, NULL, &error);
88 if (error != NULL) {
89 GtkWidget *dialog;
91 dialog = gtk_message_dialog_new (
92 GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (editor))),
93 0, GTK_MESSAGE_ERROR,
94 GTK_BUTTONS_CLOSE, _("Failed to insert text file."));
95 gtk_message_dialog_format_secondary_text (
96 GTK_MESSAGE_DIALOG (dialog), "%s.", error->message);
97 gtk_dialog_run (GTK_DIALOG (dialog));
98 gtk_widget_destroy (dialog);
100 g_clear_error (&error);
101 g_object_unref (editor);
102 return;
105 selection = e_html_editor_view_get_selection (
106 e_html_editor_get_view (editor));
107 e_html_editor_selection_insert_text (selection, contents);
108 g_free (contents);
110 g_object_unref (editor);
113 static void
114 editor_update_static_spell_actions (EHTMLEditor *editor)
116 ESpellChecker *checker;
117 EHTMLEditorView *view;
118 guint count;
120 view = e_html_editor_get_view (editor);
121 checker = e_html_editor_view_get_spell_checker (view);
123 count = e_spell_checker_count_active_languages (checker);
125 gtk_action_set_visible (ACTION (CONTEXT_SPELL_ADD), count == 1);
126 gtk_action_set_visible (ACTION (CONTEXT_SPELL_ADD_MENU), count > 1);
127 gtk_action_set_visible (ACTION (CONTEXT_SPELL_IGNORE), count > 0);
129 gtk_action_set_sensitive (ACTION (SPELL_CHECK), count > 0);
132 /*****************************************************************************
133 * Action Callbacks
134 *****************************************************************************/
136 static void
137 action_context_delete_cell_cb (GtkAction *action,
138 EHTMLEditor *editor)
140 WebKitDOMNode *sibling;
141 WebKitDOMElement *cell;
143 g_return_if_fail (editor->priv->table_cell != NULL);
145 cell = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TD");
146 if (!cell) {
147 cell = e_html_editor_dom_node_find_parent_element (
148 editor->priv->table_cell, "TH");
150 g_return_if_fail (cell != NULL);
152 sibling = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (cell));
153 if (!sibling) {
154 sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (cell));
157 webkit_dom_node_remove_child (
158 webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (cell)),
159 WEBKIT_DOM_NODE (cell), NULL);
161 if (sibling) {
162 webkit_dom_html_table_cell_element_set_col_span (
163 WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (sibling),
164 webkit_dom_html_table_cell_element_get_col_span (
165 WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (sibling)) + 1);
169 static void
170 action_context_delete_column_cb (GtkAction *action,
171 EHTMLEditor *editor)
173 WebKitDOMElement *cell, *table;
174 WebKitDOMHTMLCollection *rows;
175 gulong index, length, ii;
177 g_return_if_fail (editor->priv->table_cell != NULL);
179 /* Find TD in which the selection starts */
180 cell = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TD");
181 if (!cell) {
182 cell = e_html_editor_dom_node_find_parent_element (
183 editor->priv->table_cell, "TH");
185 g_return_if_fail (cell != NULL);
187 table = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TABLE");
188 g_return_if_fail (table != NULL);
190 rows = webkit_dom_html_table_element_get_rows (
191 WEBKIT_DOM_HTML_TABLE_ELEMENT (table));
192 length = webkit_dom_html_collection_get_length (rows);
194 index = webkit_dom_html_table_cell_element_get_cell_index (
195 WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (cell));
197 for (ii = 0; ii < length; ii++) {
198 WebKitDOMNode *row;
200 row = webkit_dom_html_collection_item (rows, ii);
202 webkit_dom_html_table_row_element_delete_cell (
203 WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row), index, NULL);
207 static void
208 action_context_delete_row_cb (GtkAction *action,
209 EHTMLEditor *editor)
211 WebKitDOMElement *row;
213 g_return_if_fail (editor->priv->table_cell != NULL);
215 row = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TR");
216 g_return_if_fail (row != NULL);
218 webkit_dom_node_remove_child (
219 webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (row)),
220 WEBKIT_DOM_NODE (row), NULL);
223 static void
224 action_context_delete_table_cb (GtkAction *action,
225 EHTMLEditor *editor)
227 WebKitDOMElement *table;
229 g_return_if_fail (editor->priv->table_cell != NULL);
231 table = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TABLE");
232 g_return_if_fail (table != NULL);
234 webkit_dom_node_remove_child (
235 webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (table)),
236 WEBKIT_DOM_NODE (table), NULL);
239 static void
240 action_context_insert_column_after_cb (GtkAction *action,
241 EHTMLEditor *editor)
243 WebKitDOMElement *cell, *row;
244 gulong index;
246 g_return_if_fail (editor->priv->table_cell != NULL);
248 cell = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TD");
249 if (!cell) {
250 cell = e_html_editor_dom_node_find_parent_element (
251 editor->priv->table_cell, "TH");
253 g_return_if_fail (cell != NULL);
255 row = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TR");
256 g_return_if_fail (row != NULL);
258 /* Get the first row in the table */
259 row = WEBKIT_DOM_ELEMENT (
260 webkit_dom_node_get_first_child (
261 webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (row))));
263 index = webkit_dom_html_table_cell_element_get_cell_index (
264 WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (cell));
266 while (row) {
267 webkit_dom_html_table_row_element_insert_cell (
268 WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row), index + 1, NULL);
270 row = WEBKIT_DOM_ELEMENT (
271 webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (row)));
275 static void
276 action_context_insert_column_before_cb (GtkAction *action,
277 EHTMLEditor *editor)
279 WebKitDOMElement *cell, *row;
280 gulong index;
282 g_return_if_fail (editor->priv->table_cell != NULL);
284 cell = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TD");
285 if (!cell) {
286 cell = e_html_editor_dom_node_find_parent_element (
287 editor->priv->table_cell, "TH");
289 g_return_if_fail (cell != NULL);
291 row = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TR");
292 g_return_if_fail (row != NULL);
294 /* Get the first row in the table */
295 row = WEBKIT_DOM_ELEMENT (
296 webkit_dom_node_get_first_child (
297 webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (row))));
299 index = webkit_dom_html_table_cell_element_get_cell_index (
300 WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (cell));
302 while (row) {
303 webkit_dom_html_table_row_element_insert_cell (
304 WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row), index - 1, NULL);
306 row = WEBKIT_DOM_ELEMENT (
307 webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (row)));
311 static void
312 action_context_insert_row_above_cb (GtkAction *action,
313 EHTMLEditor *editor)
315 WebKitDOMElement *row, *table;
316 WebKitDOMHTMLCollection *cells;
317 WebKitDOMHTMLElement *new_row;
318 gulong index, cell_count, ii;
320 g_return_if_fail (editor->priv->table_cell != NULL);
322 row = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TR");
323 g_return_if_fail (row != NULL);
325 table = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (row), "TABLE");
326 g_return_if_fail (table != NULL);
328 index = webkit_dom_html_table_row_element_get_row_index (
329 WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
331 new_row = webkit_dom_html_table_element_insert_row (
332 WEBKIT_DOM_HTML_TABLE_ELEMENT (table), index, NULL);
334 cells = webkit_dom_html_table_row_element_get_cells (
335 WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
336 cell_count = webkit_dom_html_collection_get_length (cells);
337 for (ii = 0; ii < cell_count; ii++) {
338 webkit_dom_html_table_row_element_insert_cell (
339 WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (new_row), -1, NULL);
344 static void
345 action_context_insert_row_below_cb (GtkAction *action,
346 EHTMLEditor *editor)
348 WebKitDOMElement *row, *table;
349 WebKitDOMHTMLCollection *cells;
350 WebKitDOMHTMLElement *new_row;
351 gulong index, cell_count, ii;
353 g_return_if_fail (editor->priv->table_cell != NULL);
355 row = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TR");
356 g_return_if_fail (row != NULL);
358 table = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (row), "TABLE");
359 g_return_if_fail (table != NULL);
361 index = webkit_dom_html_table_row_element_get_row_index (
362 WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
364 new_row = webkit_dom_html_table_element_insert_row (
365 WEBKIT_DOM_HTML_TABLE_ELEMENT (table), index + 1, NULL);
367 cells = webkit_dom_html_table_row_element_get_cells (
368 WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
369 cell_count = webkit_dom_html_collection_get_length (cells);
370 for (ii = 0; ii < cell_count; ii++) {
371 webkit_dom_html_table_row_element_insert_cell (
372 WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (new_row), -1, NULL);
376 static void
377 action_context_remove_link_cb (GtkAction *action,
378 EHTMLEditor *editor)
380 EHTMLEditorView *view;
381 EHTMLEditorSelection *selection;
383 view = e_html_editor_get_view (editor);
384 selection = e_html_editor_view_get_selection (view);
386 e_html_editor_selection_unlink (selection);
389 static void
390 action_context_spell_add_cb (GtkAction *action,
391 EHTMLEditor *editor)
393 ESpellChecker *spell_checker;
394 EHTMLEditorSelection *selection;
395 gchar *word;
397 spell_checker = e_html_editor_view_get_spell_checker (
398 editor->priv->html_editor_view);
399 selection = e_html_editor_view_get_selection (editor->priv->html_editor_view);
401 word = e_html_editor_selection_get_caret_word (selection);
402 if (word && *word) {
403 e_spell_checker_learn_word (spell_checker, word);
407 static void
408 action_context_spell_ignore_cb (GtkAction *action,
409 EHTMLEditor *editor)
411 ESpellChecker *spell_checker;
412 EHTMLEditorSelection *selection;
413 gchar *word;
415 spell_checker = e_html_editor_view_get_spell_checker (
416 editor->priv->html_editor_view);
417 selection = e_html_editor_view_get_selection (editor->priv->html_editor_view);
419 word = e_html_editor_selection_get_caret_word (selection);
420 if (word && *word) {
421 e_spell_checker_ignore_word (spell_checker, word);
425 static void
426 action_copy_cb (GtkAction *action,
427 EHTMLEditor *editor)
429 EHTMLEditorView *view = e_html_editor_get_view (editor);
431 if (gtk_widget_has_focus (GTK_WIDGET (view)))
432 webkit_web_view_copy_clipboard (WEBKIT_WEB_VIEW (view));
435 static void
436 action_cut_cb (GtkAction *action,
437 EHTMLEditor *editor)
439 EHTMLEditorView *view = e_html_editor_get_view (editor);
441 if (gtk_widget_has_focus (GTK_WIDGET (view)))
442 webkit_web_view_cut_clipboard (WEBKIT_WEB_VIEW (view));
445 static void
446 action_indent_cb (GtkAction *action,
447 EHTMLEditor *editor)
449 EHTMLEditorView *view = e_html_editor_get_view (editor);
451 if (gtk_widget_has_focus (GTK_WIDGET (view)))
452 e_html_editor_selection_indent (editor->priv->selection);
455 static void
456 action_insert_emoticon_cb (GtkAction *action,
457 EHTMLEditor *editor)
459 EHTMLEditorView *view;
460 EEmoticon *emoticon;
462 emoticon = e_emoticon_chooser_get_current_emoticon (
463 E_EMOTICON_CHOOSER (action));
464 g_return_if_fail (emoticon != NULL);
466 view = e_html_editor_get_view (editor);
467 e_html_editor_view_insert_smiley (view, emoticon);
470 static void
471 action_insert_html_file_cb (GtkToggleAction *action,
472 EHTMLEditor *editor)
474 GtkWidget *dialog;
475 GtkFileFilter *filter;
477 dialog = gtk_file_chooser_dialog_new (
478 _("Insert HTML File"), NULL,
479 GTK_FILE_CHOOSER_ACTION_OPEN,
480 _("_Cancel"), GTK_RESPONSE_CANCEL,
481 _("_Open"), GTK_RESPONSE_ACCEPT, NULL);
483 filter = gtk_file_filter_new ();
484 gtk_file_filter_set_name (filter, _("HTML file"));
485 gtk_file_filter_add_mime_type (filter, "text/html");
486 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
488 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
489 GFile *file;
491 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
493 /* XXX Need a way to cancel this. */
494 g_file_load_contents_async (
495 file, NULL, (GAsyncReadyCallback)
496 insert_html_file_ready_cb,
497 g_object_ref (editor));
499 g_object_unref (file);
502 gtk_widget_destroy (dialog);
505 static void
506 action_insert_image_cb (GtkAction *action,
507 EHTMLEditor *editor)
509 GtkWidget *dialog;
511 dialog = e_image_chooser_dialog_new (C_("dialog-title", "Insert Image"), NULL);
513 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
514 EHTMLEditorView *view;
515 EHTMLEditorSelection *selection;
516 gchar *uri;
518 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
520 view = e_html_editor_get_view (editor);
521 selection = e_html_editor_view_get_selection (view);
522 e_html_editor_selection_insert_image (selection, uri);
524 g_free (uri);
527 gtk_widget_destroy (dialog);
530 static void
531 action_insert_link_cb (GtkAction *action,
532 EHTMLEditor *editor)
534 if (editor->priv->link_dialog == NULL)
535 editor->priv->link_dialog =
536 e_html_editor_link_dialog_new (editor);
538 gtk_window_present (GTK_WINDOW (editor->priv->link_dialog));
541 static void
542 action_insert_rule_cb (GtkAction *action,
543 EHTMLEditor *editor)
545 if (editor->priv->hrule_dialog == NULL)
546 editor->priv->hrule_dialog =
547 e_html_editor_hrule_dialog_new (editor);
549 gtk_window_present (GTK_WINDOW (editor->priv->hrule_dialog));
552 static void
553 action_insert_table_cb (GtkAction *action,
554 EHTMLEditor *editor)
556 if (editor->priv->table_dialog == NULL)
557 editor->priv->table_dialog =
558 e_html_editor_table_dialog_new (editor);
560 gtk_window_present (GTK_WINDOW (editor->priv->table_dialog));
563 static void
564 action_insert_text_file_cb (GtkAction *action,
565 EHTMLEditor *editor)
567 GtkWidget *dialog;
568 GtkFileFilter *filter;
570 dialog = gtk_file_chooser_dialog_new (
571 _("Insert text file"), NULL,
572 GTK_FILE_CHOOSER_ACTION_OPEN,
573 _("_Cancel"), GTK_RESPONSE_CANCEL,
574 _("_Open"), GTK_RESPONSE_ACCEPT, NULL);
576 filter = gtk_file_filter_new ();
577 gtk_file_filter_set_name (filter, _("Text file"));
578 gtk_file_filter_add_mime_type (filter, "text/plain");
579 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
581 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
582 GFile *file;
584 file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
586 /* XXX Need a way to cancel this. */
587 g_file_load_contents_async (
588 file, NULL, (GAsyncReadyCallback)
589 insert_text_file_ready_cb,
590 g_object_ref (editor));
592 g_object_unref (file);
595 gtk_widget_destroy (dialog);
598 static void
599 action_language_cb (GtkToggleAction *toggle_action,
600 EHTMLEditor *editor)
602 ESpellChecker *checker;
603 EHTMLEditorView *view;
604 const gchar *language_code;
605 GtkAction *add_action;
606 gchar *action_name;
607 gboolean active;
609 view = e_html_editor_get_view (editor);
610 checker = e_html_editor_view_get_spell_checker (view);
611 language_code = gtk_action_get_name (GTK_ACTION (toggle_action));
613 active = gtk_toggle_action_get_active (toggle_action);
614 e_spell_checker_set_language_active (checker, language_code, active);
616 /* Update "Add Word To" context menu item visibility. */
617 action_name = g_strdup_printf ("context-spell-add-%s", language_code);
618 add_action = e_html_editor_get_action (editor, action_name);
619 gtk_action_set_visible (add_action, active);
620 g_free (action_name);
622 editor_update_static_spell_actions (editor);
624 g_signal_emit_by_name (editor, "spell-languages-changed");
627 static gboolean
628 update_mode_combobox (gpointer data)
630 EHTMLEditor *editor = data;
631 EHTMLEditorView *view;
632 GtkAction *action;
633 gboolean is_html;
635 if (!E_IS_HTML_EDITOR (editor))
636 return FALSE;
638 view = e_html_editor_get_view (editor);
639 is_html = e_html_editor_view_get_html_mode (view);
641 action = gtk_action_group_get_action (
642 editor->priv->core_editor_actions, "mode-html");
643 gtk_radio_action_set_current_value (
644 GTK_RADIO_ACTION (action), (is_html ? 1 : 0));
646 return FALSE;
649 static void
650 action_mode_cb (GtkRadioAction *action,
651 GtkRadioAction *current,
652 EHTMLEditor *editor)
654 GtkActionGroup *action_group;
655 EHTMLEditorView *view;
656 GtkWidget *style_combo_box;
657 gboolean is_html;
659 view = e_html_editor_get_view (editor);
660 is_html = e_html_editor_view_get_html_mode (view);
662 /* This must be done from idle callback, because apparently we can change
663 * current value in callback of current value change */
664 g_idle_add (update_mode_combobox, editor);
666 action_group = editor->priv->html_actions;
667 gtk_action_group_set_visible (action_group, is_html);
669 action_group = editor->priv->html_context_actions;
670 gtk_action_group_set_visible (action_group, is_html);
672 gtk_widget_set_sensitive (editor->priv->color_combo_box, is_html);
674 if (is_html) {
675 gtk_widget_show (editor->priv->html_toolbar);
676 } else {
677 gtk_widget_hide (editor->priv->html_toolbar);
680 /* Certain paragraph styles are HTML-only. */
681 gtk_action_set_sensitive (ACTION (STYLE_H1), is_html);
682 gtk_action_set_visible (ACTION (STYLE_H1), is_html);
683 gtk_action_set_sensitive (ACTION (STYLE_H2), is_html);
684 gtk_action_set_visible (ACTION (STYLE_H2), is_html);
685 gtk_action_set_sensitive (ACTION (STYLE_H3), is_html);
686 gtk_action_set_visible (ACTION (STYLE_H3), is_html);
687 gtk_action_set_sensitive (ACTION (STYLE_H4), is_html);
688 gtk_action_set_visible (ACTION (STYLE_H4), is_html);
689 gtk_action_set_sensitive (ACTION (STYLE_H5), is_html);
690 gtk_action_set_visible (ACTION (STYLE_H5), is_html);
691 gtk_action_set_sensitive (ACTION (STYLE_H6), is_html);
692 gtk_action_set_visible (ACTION (STYLE_H6), is_html);
693 gtk_action_set_sensitive (ACTION (STYLE_ADDRESS), is_html);
694 gtk_action_set_visible (ACTION (STYLE_ADDRESS), is_html);
696 /* Hide them from the action combo box as well */
697 style_combo_box = e_html_editor_get_style_combo_box (editor);
698 e_action_combo_box_update_model (E_ACTION_COMBO_BOX (style_combo_box));
701 static void
702 action_paste_cb (GtkAction *action,
703 EHTMLEditor *editor)
705 EHTMLEditorView *view = e_html_editor_get_view (editor);
707 /* If WebView doesn't have focus, focus it */
708 if (gtk_widget_has_focus (GTK_WIDGET (view))) {
709 webkit_web_view_paste_clipboard (WEBKIT_WEB_VIEW (view));
711 e_html_editor_view_force_spell_check (view);
715 static void
716 action_paste_as_text_cb (GtkAction *action,
717 EHTMLEditor *editor)
719 EHTMLEditorView *view = e_html_editor_get_view (editor);
721 if (gtk_widget_has_focus (GTK_WIDGET (view))) {
722 e_html_editor_view_paste_as_text (view);
723 e_html_editor_view_force_spell_check (view);
727 static void
728 action_paste_quote_cb (GtkAction *action,
729 EHTMLEditor *editor)
731 EHTMLEditorView *view = e_html_editor_get_view (editor);
733 if (gtk_widget_has_focus (GTK_WIDGET (view))) {
734 e_html_editor_view_paste_clipboard_quoted (view);
735 e_html_editor_view_force_spell_check (view);
739 static void
740 action_properties_cell_cb (GtkAction *action,
741 EHTMLEditor *editor)
743 if (editor->priv->cell_dialog == NULL) {
744 editor->priv->cell_dialog =
745 e_html_editor_cell_dialog_new (editor);
748 e_html_editor_cell_dialog_show (
749 E_HTML_EDITOR_CELL_DIALOG (editor->priv->cell_dialog),
750 editor->priv->table_cell);
753 static void
754 action_properties_image_cb (GtkAction *action,
755 EHTMLEditor *editor)
757 if (editor->priv->image_dialog == NULL) {
758 editor->priv->image_dialog =
759 e_html_editor_image_dialog_new (editor);
762 e_html_editor_image_dialog_show (
763 E_HTML_EDITOR_IMAGE_DIALOG (editor->priv->image_dialog),
764 editor->priv->image);
767 static void
768 action_properties_link_cb (GtkAction *action,
769 EHTMLEditor *editor)
771 if (editor->priv->link_dialog == NULL) {
772 editor->priv->link_dialog =
773 e_html_editor_link_dialog_new (editor);
776 gtk_window_present (GTK_WINDOW (editor->priv->link_dialog));
779 static void
780 action_properties_page_cb (GtkAction *action,
781 EHTMLEditor *editor)
783 if (editor->priv->page_dialog == NULL) {
784 editor->priv->page_dialog =
785 e_html_editor_page_dialog_new (editor);
788 gtk_window_present (GTK_WINDOW (editor->priv->page_dialog));
791 static void
792 action_properties_paragraph_cb (GtkAction *action,
793 EHTMLEditor *editor)
795 if (editor->priv->paragraph_dialog == NULL) {
796 editor->priv->paragraph_dialog =
797 e_html_editor_paragraph_dialog_new (editor);
800 gtk_window_present (GTK_WINDOW (editor->priv->paragraph_dialog));
803 static void
804 action_properties_rule_cb (GtkAction *action,
805 EHTMLEditor *editor)
807 if (editor->priv->hrule_dialog == NULL) {
808 editor->priv->hrule_dialog =
809 e_html_editor_hrule_dialog_new (editor);
812 gtk_window_present (GTK_WINDOW (editor->priv->hrule_dialog));
815 static void
816 action_properties_table_cb (GtkAction *action,
817 EHTMLEditor *editor)
819 if (editor->priv->table_dialog == NULL) {
820 editor->priv->table_dialog =
821 e_html_editor_table_dialog_new (editor);
824 gtk_window_present (GTK_WINDOW (editor->priv->table_dialog));
827 static void
828 action_properties_text_cb (GtkAction *action,
829 EHTMLEditor *editor)
831 if (editor->priv->text_dialog == NULL) {
832 editor->priv->text_dialog =
833 e_html_editor_text_dialog_new (editor);
836 gtk_window_present (GTK_WINDOW (editor->priv->text_dialog));
839 static void
840 action_redo_cb (GtkAction *action,
841 EHTMLEditor *editor)
843 EHTMLEditorView *view = e_html_editor_get_view (editor);
845 if (gtk_widget_has_focus (GTK_WIDGET (view)))
846 webkit_web_view_redo (WEBKIT_WEB_VIEW (view));
849 static void
850 action_select_all_cb (GtkAction *action,
851 EHTMLEditor *editor)
853 EHTMLEditorView *view = e_html_editor_get_view (editor);
855 if (gtk_widget_has_focus (GTK_WIDGET (view)))
856 webkit_web_view_select_all (WEBKIT_WEB_VIEW (view));
859 static void
860 action_show_find_cb (GtkAction *action,
861 EHTMLEditor *editor)
863 if (editor->priv->find_dialog == NULL) {
864 editor->priv->find_dialog = e_html_editor_find_dialog_new (editor);
865 gtk_action_set_sensitive (ACTION (FIND_AGAIN), TRUE);
868 gtk_window_present (GTK_WINDOW (editor->priv->find_dialog));
871 static void
872 action_find_again_cb (GtkAction *action,
873 EHTMLEditor *editor)
875 if (editor->priv->find_dialog == NULL)
876 return;
878 e_html_editor_find_dialog_find_next (
879 E_HTML_EDITOR_FIND_DIALOG (editor->priv->find_dialog));
882 static void
883 action_show_replace_cb (GtkAction *action,
884 EHTMLEditor *editor)
886 if (editor->priv->replace_dialog == NULL) {
887 editor->priv->replace_dialog =
888 e_html_editor_replace_dialog_new (editor);
891 gtk_window_present (GTK_WINDOW (editor->priv->replace_dialog));
894 static void
895 action_spell_check_cb (GtkAction *action,
896 EHTMLEditor *editor)
898 if (editor->priv->spell_check_dialog == NULL) {
899 editor->priv->spell_check_dialog =
900 e_html_editor_spell_check_dialog_new (editor);
903 gtk_window_present (GTK_WINDOW (editor->priv->spell_check_dialog));
906 static void
907 action_undo_cb (GtkAction *action,
908 EHTMLEditor *editor)
910 EHTMLEditorView *view = e_html_editor_get_view (editor);
912 if (gtk_widget_has_focus (GTK_WIDGET (view)))
913 webkit_web_view_undo (WEBKIT_WEB_VIEW (view));
916 static void
917 action_unindent_cb (GtkAction *action,
918 EHTMLEditor *editor)
920 EHTMLEditorView *view = e_html_editor_get_view (editor);
922 if (gtk_widget_has_focus (GTK_WIDGET (view)))
923 e_html_editor_selection_unindent (editor->priv->selection);
926 static void
927 action_wrap_lines_cb (GtkAction *action,
928 EHTMLEditor *editor)
930 EHTMLEditorView *view = e_html_editor_get_view (editor);
932 if (gtk_widget_has_focus (GTK_WIDGET (view)))
933 e_html_editor_selection_wrap_lines (editor->priv->selection);
936 static void
937 action_show_webkit_inspector_cb (GtkAction *action,
938 EHTMLEditor *editor)
940 WebKitWebInspector *inspector;
941 EHTMLEditorView *view;
943 view = e_html_editor_get_view (editor);
944 inspector = webkit_web_view_get_inspector (WEBKIT_WEB_VIEW (view));
946 webkit_web_inspector_show (inspector);
949 /*****************************************************************************
950 * Core Actions
952 * These actions are always enabled.
953 *****************************************************************************/
955 static GtkActionEntry core_entries[] = {
957 { "copy",
958 "edit-copy",
959 N_("_Copy"),
960 "<Control>c",
961 N_("Copy selected text to the clipboard"),
962 G_CALLBACK (action_copy_cb) },
964 { "cut",
965 "edit-cut",
966 N_("Cu_t"),
967 "<Control>x",
968 N_("Cut selected text to the clipboard"),
969 G_CALLBACK (action_cut_cb) },
971 { "paste",
972 "edit-paste",
973 N_("_Paste"),
974 NULL, /* Widgets are treating Ctrl + v shortcut themselves */
975 N_("Paste text from the clipboard"),
976 G_CALLBACK (action_paste_cb) },
978 { "redo",
979 "edit-redo",
980 N_("_Redo"),
981 "<Shift><Control>z",
982 N_("Redo the last undone action"),
983 G_CALLBACK (action_redo_cb) },
985 { "select-all",
986 "edit-select-all",
987 N_("Select _All"),
988 "<Control>a",
989 NULL,
990 G_CALLBACK (action_select_all_cb) },
992 { "undo",
993 "edit-undo",
994 N_("_Undo"),
995 "<Control>z",
996 N_("Undo the last action"),
997 G_CALLBACK (action_undo_cb) },
999 /* Menus */
1001 { "edit-menu",
1002 NULL,
1003 N_("_Edit"),
1004 NULL,
1005 NULL,
1006 NULL },
1008 { "file-menu",
1009 NULL,
1010 N_("_File"),
1011 NULL,
1012 NULL,
1013 NULL },
1015 { "format-menu",
1016 NULL,
1017 N_("For_mat"),
1018 NULL,
1019 NULL,
1020 NULL },
1022 { "paragraph-style-menu",
1023 NULL,
1024 N_("_Paragraph Style"),
1025 NULL,
1026 NULL,
1027 NULL },
1029 { "insert-menu",
1030 NULL,
1031 N_("_Insert"),
1032 NULL,
1033 NULL,
1034 NULL },
1036 { "justify-menu",
1037 NULL,
1038 N_("_Alignment"),
1039 NULL,
1040 NULL,
1041 NULL },
1043 { "language-menu",
1044 NULL,
1045 N_("Current _Languages"),
1046 NULL,
1047 NULL,
1048 NULL },
1050 { "view-menu",
1051 NULL,
1052 N_("_View"),
1053 NULL,
1054 NULL,
1055 NULL }
1058 static GtkActionEntry core_editor_entries[] = {
1060 { "indent",
1061 "format-indent-more",
1062 N_("_Increase Indent"),
1063 "<Control>bracketright",
1064 N_("Increase Indent"),
1065 G_CALLBACK (action_indent_cb) },
1067 { "insert-html-file",
1068 NULL,
1069 N_("_HTML File..."),
1070 NULL,
1071 NULL,
1072 G_CALLBACK (action_insert_html_file_cb) },
1074 { "insert-text-file",
1075 NULL,
1076 N_("Te_xt File..."),
1077 NULL,
1078 NULL,
1079 G_CALLBACK (action_insert_text_file_cb) },
1081 { "paste-quote",
1082 NULL,
1083 N_("Paste _Quotation"),
1084 "<Shift><Control>v",
1085 NULL,
1086 G_CALLBACK (action_paste_quote_cb) },
1088 { "show-find",
1089 "edit-find",
1090 N_("_Find..."),
1091 "<Control>f",
1092 N_("Search for text"),
1093 G_CALLBACK (action_show_find_cb) },
1095 { "find-again",
1096 NULL,
1097 N_("Find A_gain"),
1098 "<Control>g",
1099 NULL,
1100 G_CALLBACK (action_find_again_cb) },
1102 { "show-replace",
1103 "edit-find-replace",
1104 N_("Re_place..."),
1105 "<Control>h",
1106 N_("Search for and replace text"),
1107 G_CALLBACK (action_show_replace_cb) },
1109 { "spell-check",
1110 "tools-check-spelling",
1111 N_("Check _Spelling..."),
1112 "F7",
1113 NULL,
1114 G_CALLBACK (action_spell_check_cb) },
1116 { "unindent",
1117 "format-indent-less",
1118 N_("_Decrease Indent"),
1119 "<Control>bracketleft",
1120 N_("Decrease Indent"),
1121 G_CALLBACK (action_unindent_cb) },
1123 { "wrap-lines",
1124 NULL,
1125 N_("_Wrap Lines"),
1126 "<Control>k",
1127 NULL,
1128 G_CALLBACK (action_wrap_lines_cb) },
1130 { "webkit-inspector",
1131 NULL,
1132 N_("Open Inspector"),
1133 NULL,
1134 NULL,
1135 G_CALLBACK (action_show_webkit_inspector_cb) },
1138 static GtkRadioActionEntry core_justify_entries[] = {
1140 { "justify-center",
1141 "format-justify-center",
1142 N_("_Center"),
1143 "<Control>e",
1144 N_("Center Alignment"),
1145 E_HTML_EDITOR_SELECTION_ALIGNMENT_CENTER },
1147 { "justify-left",
1148 "format-justify-left",
1149 N_("_Left"),
1150 "<Control>l",
1151 N_("Left Alignment"),
1152 E_HTML_EDITOR_SELECTION_ALIGNMENT_LEFT },
1154 { "justify-right",
1155 "format-justify-right",
1156 N_("_Right"),
1157 "<Control>r",
1158 N_("Right Alignment"),
1159 E_HTML_EDITOR_SELECTION_ALIGNMENT_RIGHT }
1162 static GtkRadioActionEntry core_mode_entries[] = {
1164 { "mode-html",
1165 NULL,
1166 N_("_HTML"),
1167 NULL,
1168 N_("HTML editing mode"),
1169 TRUE }, /* e_html_editor_view_set_html_mode */
1171 { "mode-plain",
1172 NULL,
1173 N_("Plain _Text"),
1174 NULL,
1175 N_("Plain text editing mode"),
1176 FALSE } /* e_html_editor_view_set_html_mode */
1179 static GtkRadioActionEntry core_style_entries[] = {
1181 { "style-normal",
1182 NULL,
1183 N_("_Normal"),
1184 "<Control>0",
1185 NULL,
1186 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_PARAGRAPH },
1188 { "style-h1",
1189 NULL,
1190 N_("Header _1"),
1191 "<Control>1",
1192 NULL,
1193 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H1 },
1195 { "style-h2",
1196 NULL,
1197 N_("Header _2"),
1198 "<Control>2",
1199 NULL,
1200 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H2 },
1202 { "style-h3",
1203 NULL,
1204 N_("Header _3"),
1205 "<Control>3",
1206 NULL,
1207 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H3 },
1209 { "style-h4",
1210 NULL,
1211 N_("Header _4"),
1212 "<Control>4",
1213 NULL,
1214 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H4 },
1216 { "style-h5",
1217 NULL,
1218 N_("Header _5"),
1219 "<Control>5",
1220 NULL,
1221 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H5 },
1223 { "style-h6",
1224 NULL,
1225 N_("Header _6"),
1226 "<Control>6",
1227 NULL,
1228 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H6 },
1230 { "style-preformat",
1231 NULL,
1232 N_("_Preformatted"),
1233 "<Control>7",
1234 NULL,
1235 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_PRE },
1237 { "style-address",
1238 NULL,
1239 N_("A_ddress"),
1240 "<Control>8",
1241 NULL,
1242 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_ADDRESS },
1244 { "style-blockquote",
1245 NULL,
1246 N_("_Blockquote"),
1247 "<Control>9",
1248 NULL,
1249 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_BLOCKQUOTE },
1251 { "style-list-bullet",
1252 NULL,
1253 N_("_Bulleted List"),
1254 NULL,
1255 NULL,
1256 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_UNORDERED_LIST },
1258 { "style-list-roman",
1259 NULL,
1260 N_("_Roman Numeral List"),
1261 NULL,
1262 NULL,
1263 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_ORDERED_LIST_ROMAN },
1265 { "style-list-number",
1266 NULL,
1267 N_("Numbered _List"),
1268 NULL,
1269 NULL,
1270 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_ORDERED_LIST },
1272 { "style-list-alpha",
1273 NULL,
1274 N_("_Alphabetical List"),
1275 NULL,
1276 NULL,
1277 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_ORDERED_LIST_ALPHA }
1280 /*****************************************************************************
1281 * Core Actions (HTML only)
1283 * These actions are only enabled in HTML mode.
1284 *****************************************************************************/
1286 static GtkActionEntry html_entries[] = {
1288 { "insert-image",
1289 "insert-image",
1290 N_("_Image..."),
1291 NULL,
1292 /* Translators: This is an action tooltip */
1293 N_("Insert Image"),
1294 G_CALLBACK (action_insert_image_cb) },
1296 { "insert-link",
1297 "insert-link",
1298 N_("_Link..."),
1299 NULL,
1300 N_("Insert Link"),
1301 G_CALLBACK (action_insert_link_cb) },
1303 { "insert-rule",
1304 "stock_insert-rule",
1305 /* Translators: 'Rule' here means a horizontal line in an HTML text */
1306 N_("_Rule..."),
1307 NULL,
1308 /* Translators: 'Rule' here means a horizontal line in an HTML text */
1309 N_("Insert Rule"),
1310 G_CALLBACK (action_insert_rule_cb) },
1312 { "insert-table",
1313 "stock_insert-table",
1314 N_("_Table..."),
1315 NULL,
1316 N_("Insert Table"),
1317 G_CALLBACK (action_insert_table_cb) },
1319 { "properties-cell",
1320 NULL,
1321 N_("_Cell..."),
1322 NULL,
1323 NULL,
1324 G_CALLBACK (action_properties_cell_cb) },
1326 { "properties-image",
1327 NULL,
1328 N_("_Image..."),
1329 NULL,
1330 NULL,
1331 G_CALLBACK (action_properties_image_cb) },
1333 { "properties-link",
1334 NULL,
1335 N_("_Link..."),
1336 NULL,
1337 NULL,
1338 G_CALLBACK (action_properties_link_cb) },
1340 { "properties-page",
1341 NULL,
1342 N_("Pa_ge..."),
1343 NULL,
1344 NULL,
1345 G_CALLBACK (action_properties_page_cb) },
1347 { "properties-rule",
1348 NULL,
1349 /* Translators: 'Rule' here means a horizontal line in an HTML text */
1350 N_("_Rule..."),
1351 NULL,
1352 NULL,
1353 G_CALLBACK (action_properties_rule_cb) },
1355 { "properties-table",
1356 NULL,
1357 N_("_Table..."),
1358 NULL,
1359 NULL,
1360 G_CALLBACK (action_properties_table_cb) },
1362 /* Menus */
1364 { "font-size-menu",
1365 NULL,
1366 N_("Font _Size"),
1367 NULL,
1368 NULL,
1369 NULL },
1371 { "font-style-menu",
1372 NULL,
1373 N_("_Font Style"),
1374 NULL,
1375 NULL,
1376 NULL },
1378 { "paste-as-text",
1379 NULL,
1380 N_("Paste As _Text"),
1381 NULL,
1382 NULL,
1383 G_CALLBACK (action_paste_as_text_cb) },
1387 static GtkToggleActionEntry html_toggle_entries[] = {
1389 { "bold",
1390 "format-text-bold",
1391 N_("_Bold"),
1392 "<Control>b",
1393 N_("Bold"),
1394 NULL,
1395 FALSE },
1397 { "italic",
1398 "format-text-italic",
1399 N_("_Italic"),
1400 "<Control>i",
1401 N_("Italic"),
1402 NULL,
1403 FALSE },
1405 { "monospaced",
1406 "stock_text-monospaced",
1407 N_("_Plain Text"),
1408 "<Control>t",
1409 N_("Plain Text"),
1410 NULL,
1411 FALSE },
1413 { "strikethrough",
1414 "format-text-strikethrough",
1415 N_("_Strikethrough"),
1416 NULL,
1417 N_("Strikethrough"),
1418 NULL,
1419 FALSE },
1421 { "underline",
1422 "format-text-underline",
1423 N_("_Underline"),
1424 "<Control>u",
1425 N_("Underline"),
1426 NULL,
1427 FALSE }
1430 static GtkRadioActionEntry html_size_entries[] = {
1432 { "size-minus-two",
1433 NULL,
1434 /* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
1435 N_("-2"),
1436 NULL,
1437 NULL,
1438 E_HTML_EDITOR_SELECTION_FONT_SIZE_TINY },
1440 { "size-minus-one",
1441 NULL,
1442 /* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
1443 N_("-1"),
1444 NULL,
1445 NULL,
1446 E_HTML_EDITOR_SELECTION_FONT_SIZE_SMALL },
1448 { "size-plus-zero",
1449 NULL,
1450 /* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
1451 N_("+0"),
1452 NULL,
1453 NULL,
1454 E_HTML_EDITOR_SELECTION_FONT_SIZE_NORMAL },
1456 { "size-plus-one",
1457 NULL,
1458 /* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
1459 N_("+1"),
1460 NULL,
1461 NULL,
1462 E_HTML_EDITOR_SELECTION_FONT_SIZE_BIG },
1464 { "size-plus-two",
1465 NULL,
1466 /* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
1467 N_("+2"),
1468 NULL,
1469 NULL,
1470 E_HTML_EDITOR_SELECTION_FONT_SIZE_BIGGER },
1472 { "size-plus-three",
1473 NULL,
1474 /* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
1475 N_("+3"),
1476 NULL,
1477 NULL,
1478 E_HTML_EDITOR_SELECTION_FONT_SIZE_LARGE },
1480 { "size-plus-four",
1481 NULL,
1482 /* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
1483 N_("+4"),
1484 NULL,
1485 NULL,
1486 E_HTML_EDITOR_SELECTION_FONT_SIZE_VERY_LARGE }
1489 /*****************************************************************************
1490 * Context Menu Actions
1492 * These require separate action entries so we can toggle their visiblity
1493 * rather than their sensitivity as we do with main menu / toolbar actions.
1494 * Note that some of these actions use the same callback function as their
1495 * non-context sensitive counterparts.
1496 *****************************************************************************/
1498 static GtkActionEntry context_entries[] = {
1500 { "context-delete-cell",
1501 NULL,
1502 N_("Cell Contents"),
1503 NULL,
1504 NULL,
1505 G_CALLBACK (action_context_delete_cell_cb) },
1507 { "context-delete-column",
1508 NULL,
1509 N_("Column"),
1510 NULL,
1511 NULL,
1512 G_CALLBACK (action_context_delete_column_cb) },
1514 { "context-delete-row",
1515 NULL,
1516 N_("Row"),
1517 NULL,
1518 NULL,
1519 G_CALLBACK (action_context_delete_row_cb) },
1521 { "context-delete-table",
1522 NULL,
1523 N_("Table"),
1524 NULL,
1525 NULL,
1526 G_CALLBACK (action_context_delete_table_cb) },
1528 /* Menus */
1530 { "context-delete-table-menu",
1531 NULL,
1532 /* Translators: Popup menu item caption, containing all the Delete options for a table */
1533 N_("Table Delete"),
1534 NULL,
1535 NULL,
1536 NULL },
1538 { "context-input-methods-menu",
1539 NULL,
1540 N_("Input Methods"),
1541 NULL,
1542 NULL,
1543 NULL },
1545 { "context-insert-table-menu",
1546 NULL,
1547 /* Translators: Popup menu item caption, containing all the Insert options for a table */
1548 N_("Table Insert"),
1549 NULL,
1550 NULL,
1551 NULL },
1553 { "context-properties-menu",
1554 NULL,
1555 N_("Properties"),
1556 NULL,
1557 NULL,
1558 NULL },
1561 /*****************************************************************************
1562 * Context Menu Actions (HTML only)
1564 * These actions are never visible in plain-text mode. Note that some
1565 * of them use the same callback function as their non-context sensitive
1566 * counterparts.
1567 *****************************************************************************/
1569 static GtkActionEntry html_context_entries[] = {
1571 { "context-insert-column-after",
1572 NULL,
1573 N_("Column After"),
1574 NULL,
1575 NULL,
1576 G_CALLBACK (action_context_insert_column_after_cb) },
1578 { "context-insert-column-before",
1579 NULL,
1580 N_("Column Before"),
1581 NULL,
1582 NULL,
1583 G_CALLBACK (action_context_insert_column_before_cb) },
1585 { "context-insert-link",
1586 NULL,
1587 N_("Insert _Link"),
1588 NULL,
1589 NULL,
1590 G_CALLBACK (action_insert_link_cb) },
1592 { "context-insert-row-above",
1593 NULL,
1594 N_("Row Above"),
1595 NULL,
1596 NULL,
1597 G_CALLBACK (action_context_insert_row_above_cb) },
1599 { "context-insert-row-below",
1600 NULL,
1601 N_("Row Below"),
1602 NULL,
1603 NULL,
1604 G_CALLBACK (action_context_insert_row_below_cb) },
1606 { "context-insert-table",
1607 NULL,
1608 N_("Table"),
1609 NULL,
1610 NULL,
1611 G_CALLBACK (action_insert_table_cb) },
1613 { "context-properties-cell",
1614 NULL,
1615 N_("Cell..."),
1616 NULL,
1617 NULL,
1618 G_CALLBACK (action_properties_cell_cb) },
1620 { "context-properties-image",
1621 NULL,
1622 N_("Image..."),
1623 NULL,
1624 NULL,
1625 G_CALLBACK (action_properties_image_cb) },
1627 { "context-properties-link",
1628 NULL,
1629 N_("Link..."),
1630 NULL,
1631 NULL,
1632 G_CALLBACK (action_properties_link_cb) },
1634 { "context-properties-page",
1635 NULL,
1636 N_("Page..."),
1637 NULL,
1638 NULL,
1639 G_CALLBACK (action_properties_page_cb) },
1641 { "context-properties-paragraph",
1642 NULL,
1643 N_("Paragraph..."),
1644 NULL,
1645 NULL,
1646 G_CALLBACK (action_properties_paragraph_cb) },
1648 { "context-properties-rule",
1649 NULL,
1650 /* Translators: 'Rule' here means a horizontal line in an HTML text */
1651 N_("Rule..."),
1652 NULL,
1653 NULL,
1654 G_CALLBACK (action_properties_rule_cb) },
1656 { "context-properties-table",
1657 NULL,
1658 N_("Table..."),
1659 NULL,
1660 NULL,
1661 G_CALLBACK (action_properties_table_cb) },
1663 { "context-properties-text",
1664 NULL,
1665 N_("Text..."),
1666 NULL,
1667 NULL,
1668 G_CALLBACK (action_properties_text_cb) },
1670 { "context-remove-link",
1671 NULL,
1672 N_("Remove Link"),
1673 NULL,
1674 NULL,
1675 G_CALLBACK (action_context_remove_link_cb) }
1678 /*****************************************************************************
1679 * Context Menu Actions (spell checking only)
1681 * These actions are only visible when the word underneath the cursor is
1682 * misspelled.
1683 *****************************************************************************/
1685 static GtkActionEntry spell_context_entries[] = {
1687 { "context-spell-add",
1688 NULL,
1689 N_("Add Word to Dictionary"),
1690 NULL,
1691 NULL,
1692 G_CALLBACK (action_context_spell_add_cb) },
1694 { "context-spell-ignore",
1695 NULL,
1696 N_("Ignore Misspelled Word"),
1697 NULL,
1698 NULL,
1699 G_CALLBACK (action_context_spell_ignore_cb) },
1701 { "context-spell-add-menu",
1702 NULL,
1703 N_("Add Word To"),
1704 NULL,
1705 NULL,
1706 NULL },
1708 /* Menus */
1710 { "context-more-suggestions-menu",
1711 NULL,
1712 N_("More Suggestions"),
1713 NULL,
1714 NULL,
1715 NULL }
1718 static void
1719 editor_actions_setup_languages_menu (EHTMLEditor *editor)
1721 ESpellChecker *checker;
1722 EHTMLEditorView *view;
1723 GtkUIManager *manager;
1724 GtkActionGroup *action_group;
1725 GList *list, *link;
1726 guint merge_id;
1728 manager = editor->priv->manager;
1729 action_group = editor->priv->language_actions;
1730 view = e_html_editor_get_view (editor);
1731 checker = e_html_editor_view_get_spell_checker (view);
1732 merge_id = gtk_ui_manager_new_merge_id (manager);
1734 list = e_spell_checker_list_available_dicts (checker);
1736 for (link = list; link != NULL; link = g_list_next (link)) {
1737 ESpellDictionary *dictionary = link->data;
1738 GtkToggleAction *action;
1739 gboolean active;
1741 action = gtk_toggle_action_new (
1742 e_spell_dictionary_get_code (dictionary),
1743 e_spell_dictionary_get_name (dictionary),
1744 NULL, NULL);
1746 /* Do this BEFORE connecting to the "toggled" signal.
1747 * We're not prepared to invoke the signal handler yet.
1748 * The "Add Word To" actions have not yet been added. */
1749 active = e_spell_checker_get_language_active (
1750 checker, e_spell_dictionary_get_code (dictionary));
1751 gtk_toggle_action_set_active (action, active);
1753 g_signal_connect (
1754 action, "toggled",
1755 G_CALLBACK (action_language_cb), editor);
1757 gtk_action_group_add_action (
1758 action_group, GTK_ACTION (action));
1760 g_object_unref (action);
1762 gtk_ui_manager_add_ui (
1763 manager, merge_id,
1764 "/main-menu/edit-menu/language-menu",
1765 e_spell_dictionary_get_code (dictionary),
1766 e_spell_dictionary_get_code (dictionary),
1767 GTK_UI_MANAGER_AUTO, FALSE);
1770 g_list_free (list);
1773 static void
1774 editor_actions_setup_spell_check_menu (EHTMLEditor *editor)
1776 ESpellChecker *checker;
1777 GtkUIManager *manager;
1778 GtkActionGroup *action_group;
1779 GList *available_dicts, *iter;
1780 guint merge_id;
1782 manager = editor->priv->manager;
1783 action_group = editor->priv->spell_check_actions;;
1784 checker = e_html_editor_view_get_spell_checker (editor->priv->html_editor_view);
1785 available_dicts = e_spell_checker_list_available_dicts (checker);
1786 merge_id = gtk_ui_manager_new_merge_id (manager);
1788 for (iter = available_dicts; iter; iter = iter->next) {
1789 ESpellDictionary *dictionary = iter->data;
1790 GtkAction *action;
1791 const gchar *code;
1792 const gchar *name;
1793 gchar *action_label;
1794 gchar *action_name;
1796 code = e_spell_dictionary_get_code (dictionary);
1797 name = e_spell_dictionary_get_name (dictionary);
1799 /* Add a suggestion menu. */
1800 action_name = g_strdup_printf (
1801 "context-spell-suggest-%s-menu", code);
1803 action = gtk_action_new (action_name, name, NULL, NULL);
1804 gtk_action_group_add_action (action_group, action);
1805 g_object_unref (action);
1807 gtk_ui_manager_add_ui (
1808 manager, merge_id,
1809 "/context-menu/context-spell-suggest",
1810 action_name, action_name,
1811 GTK_UI_MANAGER_MENU, FALSE);
1813 g_free (action_name);
1815 /* Add an item to the "Add Word To" menu. */
1816 action_name = g_strdup_printf ("context-spell-add-%s", code);
1817 /* Translators: %s will be replaced with the actual dictionary
1818 * name, where a user can add a word to. This is part of an
1819 * "Add Word To" submenu. */
1820 action_label = g_strdup_printf (_("%s Dictionary"), name);
1822 action = gtk_action_new (
1823 action_name, action_label, NULL, NULL);
1825 g_signal_connect (
1826 action, "activate",
1827 G_CALLBACK (action_context_spell_add_cb), editor);
1829 /* Visibility is dependent on whether the
1830 * corresponding language action is active. */
1831 gtk_action_set_visible (action, FALSE);
1833 gtk_action_group_add_action (action_group, action);
1835 g_object_unref (action);
1837 gtk_ui_manager_add_ui (
1838 manager, merge_id,
1839 "/context-menu/context-spell-add-menu",
1840 action_name, action_name,
1841 GTK_UI_MANAGER_AUTO, FALSE);
1843 g_free (action_label);
1844 g_free (action_name);
1847 g_list_free (available_dicts);
1850 void
1851 editor_actions_init (EHTMLEditor *editor)
1853 GtkAction *action;
1854 GtkActionGroup *action_group;
1855 GtkUIManager *manager;
1856 const gchar *domain;
1857 EHTMLEditorView *view;
1858 GSettings *settings;
1860 g_return_if_fail (E_IS_HTML_EDITOR (editor));
1862 manager = e_html_editor_get_ui_manager (editor);
1863 domain = GETTEXT_PACKAGE;
1864 view = e_html_editor_get_view (editor);
1866 /* Core Actions */
1867 action_group = editor->priv->core_actions;
1868 gtk_action_group_set_translation_domain (action_group, domain);
1869 gtk_action_group_add_actions (
1870 action_group, core_entries,
1871 G_N_ELEMENTS (core_entries), editor);
1872 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1874 action_group = editor->priv->core_editor_actions;
1875 gtk_action_group_set_translation_domain (action_group, domain);
1876 gtk_action_group_add_actions (
1877 action_group, core_editor_entries,
1878 G_N_ELEMENTS (core_editor_entries), editor);
1879 gtk_action_group_add_radio_actions (
1880 action_group, core_justify_entries,
1881 G_N_ELEMENTS (core_justify_entries),
1882 E_HTML_EDITOR_SELECTION_ALIGNMENT_LEFT,
1883 NULL, NULL);
1884 gtk_action_group_add_radio_actions (
1885 action_group, core_mode_entries,
1886 G_N_ELEMENTS (core_mode_entries),
1887 TRUE,
1888 G_CALLBACK (action_mode_cb), editor);
1889 gtk_action_group_add_radio_actions (
1890 action_group, core_style_entries,
1891 G_N_ELEMENTS (core_style_entries),
1892 E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_PARAGRAPH,
1893 NULL, NULL);
1894 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1896 action = gtk_action_group_get_action (action_group, "mode-html");
1897 g_object_bind_property (
1898 view, "html-mode",
1899 action, "current-value",
1900 G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
1902 /* Synchronize wiget mode with the buttons */
1903 e_html_editor_view_set_html_mode (view, TRUE);
1905 /* Face Action */
1906 action = e_emoticon_action_new (
1907 "insert-emoticon", _("_Emoticon"),
1908 _("Insert Emoticon"), NULL);
1909 g_object_set (action, "icon-name", "face-smile", NULL);
1910 g_signal_connect (
1911 action, "item-activated",
1912 G_CALLBACK (action_insert_emoticon_cb), editor);
1913 gtk_action_group_add_action (action_group, action);
1914 g_object_unref (action);
1916 /* Core Actions (HTML only) */
1917 action_group = editor->priv->html_actions;
1918 gtk_action_group_set_translation_domain (action_group, domain);
1919 gtk_action_group_add_actions (
1920 action_group, html_entries,
1921 G_N_ELEMENTS (html_entries), editor);
1922 gtk_action_group_add_toggle_actions (
1923 action_group, html_toggle_entries,
1924 G_N_ELEMENTS (html_toggle_entries), editor);
1925 gtk_action_group_add_radio_actions (
1926 action_group, html_size_entries,
1927 G_N_ELEMENTS (html_size_entries),
1928 E_HTML_EDITOR_SELECTION_FONT_SIZE_NORMAL,
1929 NULL, NULL);
1930 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1932 /* Context Menu Actions */
1933 action_group = editor->priv->context_actions;
1934 gtk_action_group_set_translation_domain (action_group, domain);
1935 gtk_action_group_add_actions (
1936 action_group, context_entries,
1937 G_N_ELEMENTS (context_entries), editor);
1938 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1940 /* Context Menu Actions (HTML only) */
1941 action_group = editor->priv->html_context_actions;
1942 gtk_action_group_set_translation_domain (action_group, domain);
1943 gtk_action_group_add_actions (
1944 action_group, html_context_entries,
1945 G_N_ELEMENTS (html_context_entries), editor);
1946 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1948 /* Context Menu Actions (spell check only) */
1949 action_group = editor->priv->spell_check_actions;
1950 gtk_action_group_set_translation_domain (action_group, domain);
1951 gtk_action_group_add_actions (
1952 action_group, spell_context_entries,
1953 G_N_ELEMENTS (spell_context_entries), editor);
1954 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1956 /* Language actions are generated dynamically. */
1957 editor_actions_setup_languages_menu (editor);
1958 action_group = editor->priv->language_actions;
1959 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1961 /* Some spell check actions are generated dynamically. */
1962 action_group = editor->priv->suggestion_actions;
1963 editor_actions_setup_spell_check_menu (editor);
1964 gtk_ui_manager_insert_action_group (manager, action_group, 0);
1966 /* Do this after all language actions are initialized. */
1967 editor_update_static_spell_actions (editor);
1969 /* Fine Tuning */
1971 g_object_set (
1972 G_OBJECT (ACTION (SHOW_FIND)),
1973 "short-label", _("_Find"), NULL);
1974 g_object_set (
1975 G_OBJECT (ACTION (SHOW_REPLACE)),
1976 "short-label", _("Re_place"), NULL);
1977 g_object_set (
1978 G_OBJECT (ACTION (INSERT_IMAGE)),
1979 "short-label", _("_Image"), NULL);
1980 g_object_set (
1981 G_OBJECT (ACTION (INSERT_LINK)),
1982 "short-label", _("_Link"), NULL);
1983 g_object_set (
1984 G_OBJECT (ACTION (INSERT_RULE)),
1985 /* Translators: 'Rule' here means a horizontal line in an HTML text */
1986 "short-label", _("_Rule"), NULL);
1987 g_object_set (
1988 G_OBJECT (ACTION (INSERT_TABLE)),
1989 "short-label", _("_Table"), NULL);
1991 gtk_action_set_sensitive (ACTION (UNINDENT), FALSE);
1992 gtk_action_set_sensitive (ACTION (FIND_AGAIN), FALSE);
1994 g_object_bind_property (
1995 view, "can-redo",
1996 ACTION (REDO), "sensitive",
1997 G_BINDING_SYNC_CREATE);
1998 g_object_bind_property (
1999 view, "can-undo",
2000 ACTION (UNDO), "sensitive",
2001 G_BINDING_SYNC_CREATE);
2002 g_object_bind_property (
2003 view, "can-copy",
2004 ACTION (COPY), "sensitive",
2005 G_BINDING_SYNC_CREATE);
2006 g_object_bind_property (
2007 view, "can-cut",
2008 ACTION (CUT), "sensitive",
2009 G_BINDING_SYNC_CREATE);
2010 g_object_bind_property (
2011 view, "can-paste",
2012 ACTION (PASTE), "sensitive",
2013 G_BINDING_SYNC_CREATE);
2015 /* This is connected to JUSTIFY_LEFT action only, but
2016 * it automatically applies on all actions in the group. */
2017 g_object_bind_property (
2018 editor->priv->selection, "alignment",
2019 ACTION (JUSTIFY_LEFT), "current-value",
2020 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
2021 g_object_bind_property (
2022 editor->priv->selection, "bold",
2023 ACTION (BOLD), "active",
2024 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
2025 g_object_bind_property (
2026 editor->priv->selection, "font-size",
2027 ACTION (FONT_SIZE_GROUP), "current-value",
2028 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
2029 g_object_bind_property (
2030 editor->priv->selection, "block-format",
2031 ACTION (STYLE_NORMAL), "current-value",
2032 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
2033 g_object_bind_property (
2034 editor->priv->selection, "indented",
2035 ACTION (UNINDENT), "sensitive",
2036 G_BINDING_SYNC_CREATE);
2037 g_object_bind_property (
2038 editor->priv->selection, "italic",
2039 ACTION (ITALIC), "active",
2040 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
2041 g_object_bind_property (
2042 editor->priv->selection, "monospaced",
2043 ACTION (MONOSPACED), "active",
2044 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
2045 g_object_bind_property (
2046 editor->priv->selection, "strikethrough",
2047 ACTION (STRIKETHROUGH), "active",
2048 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
2049 g_object_bind_property (
2050 editor->priv->selection, "underline",
2051 ACTION (UNDERLINE), "active",
2052 G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
2054 /* Disable all actions and toolbars when editor is not editable */
2055 g_object_bind_property (
2056 view, "editable",
2057 editor->priv->core_editor_actions, "sensitive",
2058 G_BINDING_SYNC_CREATE);
2059 g_object_bind_property (
2060 view, "editable",
2061 editor->priv->html_actions, "sensitive",
2062 G_BINDING_SYNC_CREATE);
2063 g_object_bind_property (
2064 view, "editable",
2065 editor->priv->spell_check_actions, "sensitive",
2066 G_BINDING_SYNC_CREATE);
2067 g_object_bind_property (
2068 view, "editable",
2069 editor->priv->suggestion_actions, "sensitive",
2070 G_BINDING_SYNC_CREATE);
2072 settings = e_util_ref_settings ("org.gnome.evolution.mail");
2073 gtk_action_set_visible (
2074 ACTION (WEBKIT_INSPECTOR),
2075 g_settings_get_boolean (settings, "composer-developer-mode"));
2076 g_object_unref (settings);