/* e-html-editor-actions.c
*
* Copyright (C) 2012 Dan Vrátil
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU Lesser General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include
#include
#include "e-html-editor.h"
#include "e-html-editor-private.h"
#include "e-html-editor-actions.h"
#include "e-html-editor-utils.h"
#include "e-emoticon-action.h"
#include "e-emoticon-chooser.h"
#include "e-image-chooser-dialog.h"
#include "e-spell-checker.h"
static void
insert_html_file_ready_cb (GFile *file,
GAsyncResult *result,
EHTMLEditor *editor)
{
EHTMLEditorSelection *selection;
gchar *contents = NULL;
gsize length;
GError *error = NULL;
g_file_load_contents_finish (
file, result, &contents, &length, NULL, &error);
if (error != NULL) {
GtkWidget *dialog;
dialog = gtk_message_dialog_new (
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (editor))),
0, GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE, _("Failed to insert HTML file."));
gtk_message_dialog_format_secondary_text (
GTK_MESSAGE_DIALOG (dialog), "%s.", error->message);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_clear_error (&error);
g_object_unref (editor);
return;
}
selection = e_html_editor_view_get_selection (
e_html_editor_get_view (editor));
e_html_editor_selection_insert_html (selection, contents);
g_free (contents);
g_object_unref (editor);
}
static void
insert_text_file_ready_cb (GFile *file,
GAsyncResult *result,
EHTMLEditor *editor)
{
EHTMLEditorSelection *selection;
gchar *contents;
gsize length;
GError *error = NULL;
g_file_load_contents_finish (
file, result, &contents, &length, NULL, &error);
if (error != NULL) {
GtkWidget *dialog;
dialog = gtk_message_dialog_new (
GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (editor))),
0, GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE, _("Failed to insert text file."));
gtk_message_dialog_format_secondary_text (
GTK_MESSAGE_DIALOG (dialog), "%s.", error->message);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_clear_error (&error);
g_object_unref (editor);
return;
}
selection = e_html_editor_view_get_selection (
e_html_editor_get_view (editor));
e_html_editor_selection_insert_text (selection, contents);
g_free (contents);
g_object_unref (editor);
}
static void
editor_update_static_spell_actions (EHTMLEditor *editor)
{
ESpellChecker *checker;
EHTMLEditorView *view;
guint count;
view = e_html_editor_get_view (editor);
checker = e_html_editor_view_get_spell_checker (view);
count = e_spell_checker_count_active_languages (checker);
gtk_action_set_visible (ACTION (CONTEXT_SPELL_ADD), count == 1);
gtk_action_set_visible (ACTION (CONTEXT_SPELL_ADD_MENU), count > 1);
gtk_action_set_visible (ACTION (CONTEXT_SPELL_IGNORE), count > 0);
gtk_action_set_sensitive (ACTION (SPELL_CHECK), count > 0);
}
/*****************************************************************************
* Action Callbacks
*****************************************************************************/
static void
action_context_delete_cell_cb (GtkAction *action,
EHTMLEditor *editor)
{
WebKitDOMNode *sibling;
WebKitDOMElement *cell;
g_return_if_fail (editor->priv->table_cell != NULL);
cell = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TD");
if (!cell) {
cell = e_html_editor_dom_node_find_parent_element (
editor->priv->table_cell, "TH");
}
g_return_if_fail (cell != NULL);
sibling = webkit_dom_node_get_previous_sibling (WEBKIT_DOM_NODE (cell));
if (!sibling) {
sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (cell));
}
webkit_dom_node_remove_child (
webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (cell)),
WEBKIT_DOM_NODE (cell), NULL);
if (sibling) {
webkit_dom_html_table_cell_element_set_col_span (
WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (sibling),
webkit_dom_html_table_cell_element_get_col_span (
WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (sibling)) + 1);
}
}
static void
action_context_delete_column_cb (GtkAction *action,
EHTMLEditor *editor)
{
WebKitDOMElement *cell, *table;
WebKitDOMHTMLCollection *rows;
gulong index, length, ii;
g_return_if_fail (editor->priv->table_cell != NULL);
/* Find TD in which the selection starts */
cell = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TD");
if (!cell) {
cell = e_html_editor_dom_node_find_parent_element (
editor->priv->table_cell, "TH");
}
g_return_if_fail (cell != NULL);
table = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TABLE");
g_return_if_fail (table != NULL);
rows = webkit_dom_html_table_element_get_rows (
WEBKIT_DOM_HTML_TABLE_ELEMENT (table));
length = webkit_dom_html_collection_get_length (rows);
index = webkit_dom_html_table_cell_element_get_cell_index (
WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (cell));
for (ii = 0; ii < length; ii++) {
WebKitDOMNode *row;
row = webkit_dom_html_collection_item (rows, ii);
webkit_dom_html_table_row_element_delete_cell (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row), index, NULL);
}
}
static void
action_context_delete_row_cb (GtkAction *action,
EHTMLEditor *editor)
{
WebKitDOMElement *row;
g_return_if_fail (editor->priv->table_cell != NULL);
row = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TR");
g_return_if_fail (row != NULL);
webkit_dom_node_remove_child (
webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (row)),
WEBKIT_DOM_NODE (row), NULL);
}
static void
action_context_delete_table_cb (GtkAction *action,
EHTMLEditor *editor)
{
WebKitDOMElement *table;
g_return_if_fail (editor->priv->table_cell != NULL);
table = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TABLE");
g_return_if_fail (table != NULL);
webkit_dom_node_remove_child (
webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (table)),
WEBKIT_DOM_NODE (table), NULL);
}
static void
action_context_insert_column_after_cb (GtkAction *action,
EHTMLEditor *editor)
{
WebKitDOMElement *cell, *row;
gulong index;
g_return_if_fail (editor->priv->table_cell != NULL);
cell = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TD");
if (!cell) {
cell = e_html_editor_dom_node_find_parent_element (
editor->priv->table_cell, "TH");
}
g_return_if_fail (cell != NULL);
row = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TR");
g_return_if_fail (row != NULL);
/* Get the first row in the table */
row = WEBKIT_DOM_ELEMENT (
webkit_dom_node_get_first_child (
webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (row))));
index = webkit_dom_html_table_cell_element_get_cell_index (
WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (cell));
while (row) {
webkit_dom_html_table_row_element_insert_cell (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row), index + 1, NULL);
row = WEBKIT_DOM_ELEMENT (
webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (row)));
}
}
static void
action_context_insert_column_before_cb (GtkAction *action,
EHTMLEditor *editor)
{
WebKitDOMElement *cell, *row;
gulong index;
g_return_if_fail (editor->priv->table_cell != NULL);
cell = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TD");
if (!cell) {
cell = e_html_editor_dom_node_find_parent_element (
editor->priv->table_cell, "TH");
}
g_return_if_fail (cell != NULL);
row = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (cell), "TR");
g_return_if_fail (row != NULL);
/* Get the first row in the table */
row = WEBKIT_DOM_ELEMENT (
webkit_dom_node_get_first_child (
webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (row))));
index = webkit_dom_html_table_cell_element_get_cell_index (
WEBKIT_DOM_HTML_TABLE_CELL_ELEMENT (cell));
while (row) {
webkit_dom_html_table_row_element_insert_cell (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row), index - 1, NULL);
row = WEBKIT_DOM_ELEMENT (
webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (row)));
}
}
static void
action_context_insert_row_above_cb (GtkAction *action,
EHTMLEditor *editor)
{
WebKitDOMElement *row, *table;
WebKitDOMHTMLCollection *cells;
WebKitDOMHTMLElement *new_row;
gulong index, cell_count, ii;
g_return_if_fail (editor->priv->table_cell != NULL);
row = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TR");
g_return_if_fail (row != NULL);
table = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (row), "TABLE");
g_return_if_fail (table != NULL);
index = webkit_dom_html_table_row_element_get_row_index (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
new_row = webkit_dom_html_table_element_insert_row (
WEBKIT_DOM_HTML_TABLE_ELEMENT (table), index, NULL);
cells = webkit_dom_html_table_row_element_get_cells (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
cell_count = webkit_dom_html_collection_get_length (cells);
for (ii = 0; ii < cell_count; ii++) {
webkit_dom_html_table_row_element_insert_cell (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (new_row), -1, NULL);
}
}
static void
action_context_insert_row_below_cb (GtkAction *action,
EHTMLEditor *editor)
{
WebKitDOMElement *row, *table;
WebKitDOMHTMLCollection *cells;
WebKitDOMHTMLElement *new_row;
gulong index, cell_count, ii;
g_return_if_fail (editor->priv->table_cell != NULL);
row = e_html_editor_dom_node_find_parent_element (editor->priv->table_cell, "TR");
g_return_if_fail (row != NULL);
table = e_html_editor_dom_node_find_parent_element (WEBKIT_DOM_NODE (row), "TABLE");
g_return_if_fail (table != NULL);
index = webkit_dom_html_table_row_element_get_row_index (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
new_row = webkit_dom_html_table_element_insert_row (
WEBKIT_DOM_HTML_TABLE_ELEMENT (table), index + 1, NULL);
cells = webkit_dom_html_table_row_element_get_cells (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (row));
cell_count = webkit_dom_html_collection_get_length (cells);
for (ii = 0; ii < cell_count; ii++) {
webkit_dom_html_table_row_element_insert_cell (
WEBKIT_DOM_HTML_TABLE_ROW_ELEMENT (new_row), -1, NULL);
}
}
static void
action_context_remove_link_cb (GtkAction *action,
EHTMLEditor *editor)
{
EHTMLEditorView *view;
EHTMLEditorSelection *selection;
view = e_html_editor_get_view (editor);
selection = e_html_editor_view_get_selection (view);
e_html_editor_selection_unlink (selection);
}
static void
action_context_spell_add_cb (GtkAction *action,
EHTMLEditor *editor)
{
ESpellChecker *spell_checker;
EHTMLEditorSelection *selection;
gchar *word;
spell_checker = e_html_editor_view_get_spell_checker (
editor->priv->html_editor_view);
selection = e_html_editor_view_get_selection (editor->priv->html_editor_view);
word = e_html_editor_selection_get_caret_word (selection);
if (word && *word) {
e_spell_checker_learn_word (spell_checker, word);
}
}
static void
action_context_spell_ignore_cb (GtkAction *action,
EHTMLEditor *editor)
{
ESpellChecker *spell_checker;
EHTMLEditorSelection *selection;
gchar *word;
spell_checker = e_html_editor_view_get_spell_checker (
editor->priv->html_editor_view);
selection = e_html_editor_view_get_selection (editor->priv->html_editor_view);
word = e_html_editor_selection_get_caret_word (selection);
if (word && *word) {
e_spell_checker_ignore_word (spell_checker, word);
}
}
static void
action_copy_cb (GtkAction *action,
EHTMLEditor *editor)
{
webkit_web_view_copy_clipboard (
WEBKIT_WEB_VIEW (e_html_editor_get_view (editor)));
}
static void
action_cut_cb (GtkAction *action,
EHTMLEditor *editor)
{
webkit_web_view_cut_clipboard (
WEBKIT_WEB_VIEW (e_html_editor_get_view (editor)));
}
static void
action_indent_cb (GtkAction *action,
EHTMLEditor *editor)
{
e_html_editor_selection_indent (editor->priv->selection);
}
static void
action_insert_emoticon_cb (GtkAction *action,
EHTMLEditor *editor)
{
EHTMLEditorView *view;
EEmoticon *emoticon;
emoticon = e_emoticon_chooser_get_current_emoticon (
E_EMOTICON_CHOOSER (action));
g_return_if_fail (emoticon != NULL);
view = e_html_editor_get_view (editor);
e_html_editor_view_insert_smiley (view, emoticon);
}
static void
action_insert_html_file_cb (GtkToggleAction *action,
EHTMLEditor *editor)
{
GtkWidget *dialog;
GtkFileFilter *filter;
dialog = gtk_file_chooser_dialog_new (
_("Insert HTML File"), NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("HTML file"));
gtk_file_filter_add_mime_type (filter, "text/html");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
GFile *file;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
/* XXX Need a way to cancel this. */
g_file_load_contents_async (
file, NULL, (GAsyncReadyCallback)
insert_html_file_ready_cb,
g_object_ref (editor));
g_object_unref (file);
}
gtk_widget_destroy (dialog);
}
static void
action_insert_image_cb (GtkAction *action,
EHTMLEditor *editor)
{
GtkWidget *dialog;
dialog = e_image_chooser_dialog_new (_("Insert Image"), NULL);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
EHTMLEditorView *view;
EHTMLEditorSelection *selection;
gchar *uri;
uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
view = e_html_editor_get_view (editor);
selection = e_html_editor_view_get_selection (view);
e_html_editor_selection_insert_image (selection, uri);
g_free (uri);
}
gtk_widget_destroy (dialog);
}
static void
action_insert_link_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->link_dialog == NULL)
editor->priv->link_dialog =
e_html_editor_link_dialog_new (editor);
gtk_window_present (GTK_WINDOW (editor->priv->link_dialog));
}
static void
action_insert_rule_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->hrule_dialog == NULL)
editor->priv->hrule_dialog =
e_html_editor_hrule_dialog_new (editor);
gtk_window_present (GTK_WINDOW (editor->priv->hrule_dialog));
}
static void
action_insert_table_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->table_dialog == NULL)
editor->priv->table_dialog =
e_html_editor_table_dialog_new (editor);
gtk_window_present (GTK_WINDOW (editor->priv->table_dialog));
}
static void
action_insert_text_file_cb (GtkAction *action,
EHTMLEditor *editor)
{
GtkWidget *dialog;
GtkFileFilter *filter;
dialog = gtk_file_chooser_dialog_new (
_("Insert text file"), NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("Text file"));
gtk_file_filter_add_mime_type (filter, "text/plain");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
GFile *file;
file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
/* XXX Need a way to cancel this. */
g_file_load_contents_async (
file, NULL, (GAsyncReadyCallback)
insert_text_file_ready_cb,
g_object_ref (editor));
g_object_unref (file);
}
gtk_widget_destroy (dialog);
}
static void
action_language_cb (GtkToggleAction *toggle_action,
EHTMLEditor *editor)
{
ESpellChecker *checker;
EHTMLEditorView *view;
const gchar *language_code;
GtkAction *add_action;
gchar *action_name;
gboolean active;
view = e_html_editor_get_view (editor);
checker = e_html_editor_view_get_spell_checker (view);
language_code = gtk_action_get_name (GTK_ACTION (toggle_action));
active = gtk_toggle_action_get_active (toggle_action);
e_spell_checker_set_language_active (checker, language_code, active);
/* Update "Add Word To" context menu item visibility. */
action_name = g_strdup_printf ("context-spell-add-%s", language_code);
add_action = e_html_editor_get_action (editor, action_name);
gtk_action_set_visible (add_action, active);
g_free (action_name);
editor_update_static_spell_actions (editor);
g_signal_emit_by_name (editor, "spell-languages-changed");
}
static gboolean
update_mode_combobox (gpointer data)
{
EHTMLEditor *editor = data;
EHTMLEditorView *view;
GtkAction *action;
gboolean is_html;
if (!E_IS_HTML_EDITOR (editor))
return FALSE;
view = e_html_editor_get_view (editor);
is_html = e_html_editor_view_get_html_mode (view);
action = gtk_action_group_get_action (
editor->priv->core_actions, "mode-html");
gtk_radio_action_set_current_value (
GTK_RADIO_ACTION (action), (is_html ? 1 : 0));
return FALSE;
}
static void
action_mode_cb (GtkRadioAction *action,
GtkRadioAction *current,
EHTMLEditor *editor)
{
GtkActionGroup *action_group;
EHTMLEditorView *view;
GtkWidget *style_combo_box;
gboolean is_html;
view = e_html_editor_get_view (editor);
is_html = e_html_editor_view_get_html_mode (view);
/* This must be done from idle callback, because apparently we can change
* current value in callback of current value change */
g_idle_add (update_mode_combobox, editor);
action_group = editor->priv->html_actions;
gtk_action_group_set_sensitive (action_group, is_html);
action_group = editor->priv->html_context_actions;
gtk_action_group_set_visible (action_group, is_html);
gtk_widget_set_sensitive (editor->priv->color_combo_box, is_html);
if (is_html) {
gtk_widget_show (editor->priv->html_toolbar);
} else {
gtk_widget_hide (editor->priv->html_toolbar);
}
/* Certain paragraph styles are HTML-only. */
gtk_action_set_sensitive (ACTION (STYLE_H1), is_html);
gtk_action_set_visible (ACTION (STYLE_H1), is_html);
gtk_action_set_sensitive (ACTION (STYLE_H2), is_html);
gtk_action_set_visible (ACTION (STYLE_H2), is_html);
gtk_action_set_sensitive (ACTION (STYLE_H3), is_html);
gtk_action_set_visible (ACTION (STYLE_H3), is_html);
gtk_action_set_sensitive (ACTION (STYLE_H4), is_html);
gtk_action_set_visible (ACTION (STYLE_H4), is_html);
gtk_action_set_sensitive (ACTION (STYLE_H5), is_html);
gtk_action_set_visible (ACTION (STYLE_H5), is_html);
gtk_action_set_sensitive (ACTION (STYLE_H6), is_html);
gtk_action_set_visible (ACTION (STYLE_H6), is_html);
gtk_action_set_sensitive (ACTION (STYLE_ADDRESS), is_html);
gtk_action_set_visible (ACTION (STYLE_ADDRESS), is_html);
/* Hide them from the action combo box as well */
style_combo_box = e_html_editor_get_style_combo_box (editor);
e_action_combo_box_update_model (E_ACTION_COMBO_BOX (style_combo_box));
}
static void
action_paste_cb (GtkAction *action,
EHTMLEditor *editor)
{
EHTMLEditorView *view = e_html_editor_get_view (editor);
/* Paste only if WebView has focus */
if (gtk_widget_has_focus (GTK_WIDGET (view))) {
webkit_web_view_paste_clipboard (
WEBKIT_WEB_VIEW (view));
e_html_editor_view_force_spell_check (view);
}
}
static void
action_paste_quote_cb (GtkAction *action,
EHTMLEditor *editor)
{
e_html_editor_view_paste_clipboard_quoted (
e_html_editor_get_view (editor));
e_html_editor_view_force_spell_check (
e_html_editor_get_view (editor));
}
static void
action_properties_cell_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->cell_dialog == NULL) {
editor->priv->cell_dialog =
e_html_editor_cell_dialog_new (editor);
}
e_html_editor_cell_dialog_show (
E_HTML_EDITOR_CELL_DIALOG (editor->priv->cell_dialog),
editor->priv->table_cell);
}
static void
action_properties_image_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->image_dialog == NULL) {
editor->priv->image_dialog =
e_html_editor_image_dialog_new (editor);
}
e_html_editor_image_dialog_show (
E_HTML_EDITOR_IMAGE_DIALOG (editor->priv->image_dialog),
editor->priv->image);
}
static void
action_properties_link_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->link_dialog == NULL) {
editor->priv->link_dialog =
e_html_editor_link_dialog_new (editor);
}
gtk_window_present (GTK_WINDOW (editor->priv->link_dialog));
}
static void
action_properties_page_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->page_dialog == NULL) {
editor->priv->page_dialog =
e_html_editor_page_dialog_new (editor);
}
gtk_window_present (GTK_WINDOW (editor->priv->page_dialog));
}
static void
action_properties_paragraph_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->paragraph_dialog == NULL) {
editor->priv->paragraph_dialog =
e_html_editor_paragraph_dialog_new (editor);
}
gtk_window_present (GTK_WINDOW (editor->priv->paragraph_dialog));
}
static void
action_properties_rule_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->hrule_dialog == NULL) {
editor->priv->hrule_dialog =
e_html_editor_hrule_dialog_new (editor);
}
gtk_window_present (GTK_WINDOW (editor->priv->hrule_dialog));
}
static void
action_properties_table_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->table_dialog == NULL) {
editor->priv->table_dialog =
e_html_editor_table_dialog_new (editor);
}
gtk_window_present (GTK_WINDOW (editor->priv->table_dialog));
}
static void
action_properties_text_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->text_dialog == NULL) {
editor->priv->text_dialog =
e_html_editor_text_dialog_new (editor);
}
gtk_window_present (GTK_WINDOW (editor->priv->text_dialog));
}
static void
action_redo_cb (GtkAction *action,
EHTMLEditor *editor)
{
webkit_web_view_redo (
WEBKIT_WEB_VIEW (e_html_editor_get_view (editor)));
}
static void
action_select_all_cb (GtkAction *action,
EHTMLEditor *editor)
{
webkit_web_view_select_all (
WEBKIT_WEB_VIEW (e_html_editor_get_view (editor)));
}
static void
action_show_find_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->find_dialog == NULL) {
editor->priv->find_dialog = e_html_editor_find_dialog_new (editor);
gtk_action_set_sensitive (ACTION (FIND_AGAIN), TRUE);
}
gtk_window_present (GTK_WINDOW (editor->priv->find_dialog));
}
static void
action_find_again_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->find_dialog == NULL) {
return;
}
e_html_editor_find_dialog_find_next (
E_HTML_EDITOR_FIND_DIALOG (editor->priv->find_dialog));
}
static void
action_show_replace_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->replace_dialog == NULL) {
editor->priv->replace_dialog =
e_html_editor_replace_dialog_new (editor);
}
gtk_window_present (GTK_WINDOW (editor->priv->replace_dialog));
}
static void
action_spell_check_cb (GtkAction *action,
EHTMLEditor *editor)
{
if (editor->priv->spell_check_dialog == NULL) {
editor->priv->spell_check_dialog =
e_html_editor_spell_check_dialog_new (editor);
}
gtk_window_present (GTK_WINDOW (editor->priv->spell_check_dialog));
}
static void
action_undo_cb (GtkAction *action,
EHTMLEditor *editor)
{
webkit_web_view_undo (
WEBKIT_WEB_VIEW (e_html_editor_get_view (editor)));
}
static void
action_unindent_cb (GtkAction *action,
EHTMLEditor *editor)
{
e_html_editor_selection_unindent (editor->priv->selection);
}
static void
action_wrap_lines_cb (GtkAction *action,
EHTMLEditor *editor)
{
e_html_editor_selection_wrap_lines (editor->priv->selection);
}
static void
action_show_webkit_inspector_cb (GtkAction *action,
EHTMLEditor *editor)
{
WebKitWebInspector *inspector;
EHTMLEditorView *view;
view = e_html_editor_get_view (editor);
inspector = webkit_web_view_get_inspector (WEBKIT_WEB_VIEW (view));
webkit_web_inspector_show (inspector);
}
/*****************************************************************************
* Core Actions
*
* These actions are always enabled.
*****************************************************************************/
static GtkActionEntry core_entries[] = {
{ "copy",
GTK_STOCK_COPY,
N_("_Copy"),
"c",
N_("Copy selected text to the clipboard"),
G_CALLBACK (action_copy_cb) },
{ "cut",
GTK_STOCK_CUT,
N_("Cu_t"),
"x",
N_("Cut selected text to the clipboard"),
G_CALLBACK (action_cut_cb) },
{ "indent",
GTK_STOCK_INDENT,
N_("_Increase Indent"),
"bracketright",
N_("Increase Indent"),
G_CALLBACK (action_indent_cb) },
{ "insert-html-file",
NULL,
N_("_HTML File..."),
NULL,
NULL,
G_CALLBACK (action_insert_html_file_cb) },
{ "insert-text-file",
NULL,
N_("Te_xt File..."),
NULL,
NULL,
G_CALLBACK (action_insert_text_file_cb) },
{ "paste",
GTK_STOCK_PASTE,
N_("_Paste"),
"v",
N_("Paste text from the clipboard"),
G_CALLBACK (action_paste_cb) },
{ "paste-quote",
NULL,
N_("Paste _Quotation"),
"v",
NULL,
G_CALLBACK (action_paste_quote_cb) },
{ "redo",
GTK_STOCK_REDO,
N_("_Redo"),
"z",
N_("Redo the last undone action"),
G_CALLBACK (action_redo_cb) },
{ "select-all",
GTK_STOCK_SELECT_ALL,
N_("Select _All"),
"a",
NULL,
G_CALLBACK (action_select_all_cb) },
{ "show-find",
GTK_STOCK_FIND,
N_("_Find..."),
"f",
N_("Search for text"),
G_CALLBACK (action_show_find_cb) },
{ "find-again",
NULL,
N_("Find A_gain"),
"g",
NULL,
G_CALLBACK (action_find_again_cb) },
{ "show-replace",
GTK_STOCK_FIND_AND_REPLACE,
N_("Re_place..."),
"h",
N_("Search for and replace text"),
G_CALLBACK (action_show_replace_cb) },
{ "spell-check",
GTK_STOCK_SPELL_CHECK,
N_("Check _Spelling..."),
"F7",
NULL,
G_CALLBACK (action_spell_check_cb) },
{ "undo",
GTK_STOCK_UNDO,
N_("_Undo"),
"z",
N_("Undo the last action"),
G_CALLBACK (action_undo_cb) },
{ "unindent",
GTK_STOCK_UNINDENT,
N_("_Decrease Indent"),
"bracketleft",
N_("Decrease Indent"),
G_CALLBACK (action_unindent_cb) },
{ "wrap-lines",
NULL,
N_("_Wrap Lines"),
"k",
NULL,
G_CALLBACK (action_wrap_lines_cb) },
{ "webkit-inspector",
NULL,
N_("Open Inspector"),
NULL,
NULL,
G_CALLBACK (action_show_webkit_inspector_cb) },
/* Menus */
{ "edit-menu",
NULL,
N_("_Edit"),
NULL,
NULL,
NULL },
{ "file-menu",
NULL,
N_("_File"),
NULL,
NULL,
NULL },
{ "format-menu",
NULL,
N_("For_mat"),
NULL,
NULL,
NULL },
{ "paragraph-style-menu",
NULL,
N_("_Paragraph Style"),
NULL,
NULL,
NULL },
{ "insert-menu",
NULL,
N_("_Insert"),
NULL,
NULL,
NULL },
{ "justify-menu",
NULL,
N_("_Alignment"),
NULL,
NULL,
NULL },
{ "language-menu",
NULL,
N_("Current _Languages"),
NULL,
NULL,
NULL },
{ "view-menu",
NULL,
N_("_View"),
NULL,
NULL,
NULL }
};
static GtkRadioActionEntry core_justify_entries[] = {
{ "justify-center",
GTK_STOCK_JUSTIFY_CENTER,
N_("_Center"),
"e",
N_("Center Alignment"),
E_HTML_EDITOR_SELECTION_ALIGNMENT_CENTER },
{ "justify-left",
GTK_STOCK_JUSTIFY_LEFT,
N_("_Left"),
"l",
N_("Left Alignment"),
E_HTML_EDITOR_SELECTION_ALIGNMENT_LEFT },
{ "justify-right",
GTK_STOCK_JUSTIFY_RIGHT,
N_("_Right"),
"r",
N_("Right Alignment"),
E_HTML_EDITOR_SELECTION_ALIGNMENT_RIGHT }
};
static GtkRadioActionEntry core_mode_entries[] = {
{ "mode-html",
NULL,
N_("_HTML"),
NULL,
N_("HTML editing mode"),
TRUE }, /* e_html_editor_view_set_html_mode */
{ "mode-plain",
NULL,
N_("Plain _Text"),
NULL,
N_("Plain text editing mode"),
FALSE } /* e_html_editor_view_set_html_mode */
};
static GtkRadioActionEntry core_style_entries[] = {
{ "style-normal",
NULL,
N_("_Normal"),
"0",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_PARAGRAPH },
{ "style-h1",
NULL,
N_("Header _1"),
"1",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H1 },
{ "style-h2",
NULL,
N_("Header _2"),
"2",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H2 },
{ "style-h3",
NULL,
N_("Header _3"),
"3",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H3 },
{ "style-h4",
NULL,
N_("Header _4"),
"4",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H4 },
{ "style-h5",
NULL,
N_("Header _5"),
"5",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H5 },
{ "style-h6",
NULL,
N_("Header _6"),
"6",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_H6 },
{ "style-preformat",
NULL,
N_("_Preformatted"),
"7",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_PRE },
{ "style-address",
NULL,
N_("A_ddress"),
"8",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_ADDRESS },
{ "style-blockquote",
NULL,
N_("_Blockquote"),
"9",
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_BLOCKQUOTE },
{ "style-list-bullet",
NULL,
N_("_Bulleted List"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_UNORDERED_LIST },
{ "style-list-roman",
NULL,
N_("_Roman Numeral List"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_ORDERED_LIST_ROMAN },
{ "style-list-number",
NULL,
N_("Numbered _List"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_ORDERED_LIST },
{ "style-list-alpha",
NULL,
N_("_Alphabetical List"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_ORDERED_LIST_ALPHA }
};
/*****************************************************************************
* Core Actions (HTML only)
*
* These actions are only enabled in HTML mode.
*****************************************************************************/
static GtkActionEntry html_entries[] = {
{ "insert-image",
"insert-image",
N_("_Image..."),
NULL,
N_("Insert Image"),
G_CALLBACK (action_insert_image_cb) },
{ "insert-link",
"insert-link",
N_("_Link..."),
NULL,
N_("Insert Link"),
G_CALLBACK (action_insert_link_cb) },
{ "insert-rule",
"stock_insert-rule",
/* Translators: 'Rule' here means a horizontal line in an HTML text */
N_("_Rule..."),
NULL,
/* Translators: 'Rule' here means a horizontal line in an HTML text */
N_("Insert Rule"),
G_CALLBACK (action_insert_rule_cb) },
{ "insert-table",
"stock_insert-table",
N_("_Table..."),
NULL,
N_("Insert Table"),
G_CALLBACK (action_insert_table_cb) },
{ "properties-cell",
NULL,
N_("_Cell..."),
NULL,
NULL,
G_CALLBACK (action_properties_cell_cb) },
{ "properties-image",
NULL,
N_("_Image..."),
NULL,
NULL,
G_CALLBACK (action_properties_image_cb) },
{ "properties-link",
NULL,
N_("_Link..."),
NULL,
NULL,
G_CALLBACK (action_properties_link_cb) },
{ "properties-page",
NULL,
N_("Pa_ge..."),
NULL,
NULL,
G_CALLBACK (action_properties_page_cb) },
{ "properties-rule",
NULL,
/* Translators: 'Rule' here means a horizontal line in an HTML text */
N_("_Rule..."),
NULL,
NULL,
G_CALLBACK (action_properties_rule_cb) },
{ "properties-table",
NULL,
N_("_Table..."),
NULL,
NULL,
G_CALLBACK (action_properties_table_cb) },
/* Menus */
{ "font-size-menu",
NULL,
N_("Font _Size"),
NULL,
NULL,
NULL },
{ "font-style-menu",
NULL,
N_("_Font Style"),
NULL,
NULL,
NULL },
};
static GtkToggleActionEntry html_toggle_entries[] = {
{ "bold",
GTK_STOCK_BOLD,
N_("_Bold"),
"b",
N_("Bold"),
NULL,
FALSE },
{ "italic",
GTK_STOCK_ITALIC,
N_("_Italic"),
"i",
N_("Italic"),
NULL,
FALSE },
{ "monospaced",
"stock_text-monospaced",
N_("_Plain Text"),
"t",
N_("Plain Text"),
NULL,
FALSE },
{ "strikethrough",
GTK_STOCK_STRIKETHROUGH,
N_("_Strikethrough"),
NULL,
N_("Strikethrough"),
NULL,
FALSE },
{ "underline",
GTK_STOCK_UNDERLINE,
N_("_Underline"),
"u",
N_("Underline"),
NULL,
FALSE }
};
static GtkRadioActionEntry html_size_entries[] = {
{ "size-minus-two",
NULL,
/* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
N_("-2"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_FONT_SIZE_TINY },
{ "size-minus-one",
NULL,
/* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
N_("-1"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_FONT_SIZE_SMALL },
{ "size-plus-zero",
NULL,
/* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
N_("+0"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_FONT_SIZE_NORMAL },
{ "size-plus-one",
NULL,
/* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
N_("+1"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_FONT_SIZE_BIG },
{ "size-plus-two",
NULL,
/* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
N_("+2"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_FONT_SIZE_BIGGER },
{ "size-plus-three",
NULL,
/* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
N_("+3"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_FONT_SIZE_LARGE },
{ "size-plus-four",
NULL,
/* Translators: This is a font size level. It is shown on a tool bar. Please keep it as short as possible. */
N_("+4"),
NULL,
NULL,
E_HTML_EDITOR_SELECTION_FONT_SIZE_VERY_LARGE }
};
/*****************************************************************************
* Context Menu Actions
*
* These require separate action entries so we can toggle their visiblity
* rather than their sensitivity as we do with main menu / toolbar actions.
* Note that some of these actions use the same callback function as their
* non-context sensitive counterparts.
*****************************************************************************/
static GtkActionEntry context_entries[] = {
{ "context-delete-cell",
NULL,
N_("Cell Contents"),
NULL,
NULL,
G_CALLBACK (action_context_delete_cell_cb) },
{ "context-delete-column",
NULL,
N_("Column"),
NULL,
NULL,
G_CALLBACK (action_context_delete_column_cb) },
{ "context-delete-row",
NULL,
N_("Row"),
NULL,
NULL,
G_CALLBACK (action_context_delete_row_cb) },
{ "context-delete-table",
NULL,
N_("Table"),
NULL,
NULL,
G_CALLBACK (action_context_delete_table_cb) },
/* Menus */
{ "context-delete-table-menu",
NULL,
/* Translators: Popup menu item caption, containing all the Delete options for a table */
N_("Table Delete"),
NULL,
NULL,
NULL },
{ "context-input-methods-menu",
NULL,
N_("Input Methods"),
NULL,
NULL,
NULL },
{ "context-insert-table-menu",
NULL,
/* Translators: Popup menu item caption, containing all the Insert options for a table */
N_("Table Insert"),
NULL,
NULL,
NULL },
{ "context-properties-menu",
NULL,
N_("Properties"),
NULL,
NULL,
NULL },
};
/*****************************************************************************
* Context Menu Actions (HTML only)
*
* These actions are never visible in plain-text mode. Note that some
* of them use the same callback function as their non-context sensitive
* counterparts.
*****************************************************************************/
static GtkActionEntry html_context_entries[] = {
{ "context-insert-column-after",
NULL,
N_("Column After"),
NULL,
NULL,
G_CALLBACK (action_context_insert_column_after_cb) },
{ "context-insert-column-before",
NULL,
N_("Column Before"),
NULL,
NULL,
G_CALLBACK (action_context_insert_column_before_cb) },
{ "context-insert-link",
NULL,
N_("Insert _Link"),
NULL,
NULL,
G_CALLBACK (action_insert_link_cb) },
{ "context-insert-row-above",
NULL,
N_("Row Above"),
NULL,
NULL,
G_CALLBACK (action_context_insert_row_above_cb) },
{ "context-insert-row-below",
NULL,
N_("Row Below"),
NULL,
NULL,
G_CALLBACK (action_context_insert_row_below_cb) },
{ "context-insert-table",
NULL,
N_("Table"),
NULL,
NULL,
G_CALLBACK (action_insert_table_cb) },
{ "context-properties-cell",
NULL,
N_("Cell..."),
NULL,
NULL,
G_CALLBACK (action_properties_cell_cb) },
{ "context-properties-image",
NULL,
N_("Image..."),
NULL,
NULL,
G_CALLBACK (action_properties_image_cb) },
{ "context-properties-link",
NULL,
N_("Link..."),
NULL,
NULL,
G_CALLBACK (action_properties_link_cb) },
{ "context-properties-page",
NULL,
N_("Page..."),
NULL,
NULL,
G_CALLBACK (action_properties_page_cb) },
{ "context-properties-paragraph",
NULL,
N_("Paragraph..."),
NULL,
NULL,
G_CALLBACK (action_properties_paragraph_cb) },
{ "context-properties-rule",
NULL,
/* Translators: 'Rule' here means a horizontal line in an HTML text */
N_("Rule..."),
NULL,
NULL,
G_CALLBACK (action_properties_rule_cb) },
{ "context-properties-table",
NULL,
N_("Table..."),
NULL,
NULL,
G_CALLBACK (action_properties_table_cb) },
{ "context-properties-text",
NULL,
N_("Text..."),
NULL,
NULL,
G_CALLBACK (action_properties_text_cb) },
{ "context-remove-link",
NULL,
N_("Remove Link"),
NULL,
NULL,
G_CALLBACK (action_context_remove_link_cb) }
};
/*****************************************************************************
* Context Menu Actions (spell checking only)
*
* These actions are only visible when the word underneath the cursor is
* misspelled.
*****************************************************************************/
static GtkActionEntry spell_context_entries[] = {
{ "context-spell-add",
NULL,
N_("Add Word to Dictionary"),
NULL,
NULL,
G_CALLBACK (action_context_spell_add_cb) },
{ "context-spell-ignore",
NULL,
N_("Ignore Misspelled Word"),
NULL,
NULL,
G_CALLBACK (action_context_spell_ignore_cb) },
{ "context-spell-add-menu",
NULL,
N_("Add Word To"),
NULL,
NULL,
NULL },
/* Menus */
{ "context-more-suggestions-menu",
NULL,
N_("More Suggestions"),
NULL,
NULL,
NULL }
};
static void
editor_actions_setup_languages_menu (EHTMLEditor *editor)
{
ESpellChecker *checker;
EHTMLEditorView *view;
GtkUIManager *manager;
GtkActionGroup *action_group;
GList *list, *link;
guint merge_id;
manager = editor->priv->manager;
action_group = editor->priv->language_actions;
view = e_html_editor_get_view (editor);
checker = e_html_editor_view_get_spell_checker (view);
merge_id = gtk_ui_manager_new_merge_id (manager);
list = e_spell_checker_list_available_dicts (checker);
for (link = list; link != NULL; link = g_list_next (link)) {
ESpellDictionary *dictionary = link->data;
GtkToggleAction *action;
gboolean active;
action = gtk_toggle_action_new (
e_spell_dictionary_get_code (dictionary),
e_spell_dictionary_get_name (dictionary),
NULL, NULL);
/* Do this BEFORE connecting to the "toggled" signal.
* We're not prepared to invoke the signal handler yet.
* The "Add Word To" actions have not yet been added. */
active = e_spell_checker_get_language_active (
checker, e_spell_dictionary_get_code (dictionary));
gtk_toggle_action_set_active (action, active);
g_signal_connect (
action, "toggled",
G_CALLBACK (action_language_cb), editor);
gtk_action_group_add_action (
action_group, GTK_ACTION (action));
g_object_unref (action);
gtk_ui_manager_add_ui (
manager, merge_id,
"/main-menu/edit-menu/language-menu",
e_spell_dictionary_get_code (dictionary),
e_spell_dictionary_get_code (dictionary),
GTK_UI_MANAGER_AUTO, FALSE);
}
g_list_free (list);
}
static void
editor_actions_setup_spell_check_menu (EHTMLEditor *editor)
{
ESpellChecker *checker;
GtkUIManager *manager;
GtkActionGroup *action_group;
GList *available_dicts, *iter;
guint merge_id;
manager = editor->priv->manager;
action_group = editor->priv->spell_check_actions;;
checker = e_html_editor_view_get_spell_checker (editor->priv->html_editor_view);
available_dicts = e_spell_checker_list_available_dicts (checker);
merge_id = gtk_ui_manager_new_merge_id (manager);
for (iter = available_dicts; iter; iter = iter->next) {
ESpellDictionary *dictionary = iter->data;
GtkAction *action;
const gchar *code;
const gchar *name;
gchar *action_label;
gchar *action_name;
code = e_spell_dictionary_get_code (dictionary);
name = e_spell_dictionary_get_name (dictionary);
/* Add a suggestion menu. */
action_name = g_strdup_printf (
"context-spell-suggest-%s-menu", code);
action = gtk_action_new (action_name, name, NULL, NULL);
gtk_action_group_add_action (action_group, action);
g_object_unref (action);
gtk_ui_manager_add_ui (
manager, merge_id,
"/context-menu/context-spell-suggest",
action_name, action_name,
GTK_UI_MANAGER_MENU, FALSE);
g_free (action_name);
/* Add an item to the "Add Word To" menu. */
action_name = g_strdup_printf ("context-spell-add-%s", code);
/* Translators: %s will be replaced with the actual dictionary
* name, where a user can add a word to. This is part of an
* "Add Word To" submenu. */
action_label = g_strdup_printf (_("%s Dictionary"), name);
action = gtk_action_new (
action_name, action_label, NULL, NULL);
g_signal_connect (
action, "activate",
G_CALLBACK (action_context_spell_add_cb), editor);
/* Visibility is dependent on whether the
* corresponding language action is active. */
gtk_action_set_visible (action, FALSE);
gtk_action_group_add_action (action_group, action);
g_object_unref (action);
gtk_ui_manager_add_ui (
manager, merge_id,
"/context-menu/context-spell-add-menu",
action_name, action_name,
GTK_UI_MANAGER_AUTO, FALSE);
g_free (action_label);
g_free (action_name);
}
g_list_free (available_dicts);
}
void
editor_actions_init (EHTMLEditor *editor)
{
GtkAction *action;
GtkActionGroup *action_group;
GtkUIManager *manager;
const gchar *domain;
EHTMLEditorView *view;
GSettings *settings;
g_return_if_fail (E_IS_HTML_EDITOR (editor));
manager = e_html_editor_get_ui_manager (editor);
domain = GETTEXT_PACKAGE;
view = e_html_editor_get_view (editor);
/* Core Actions */
action_group = editor->priv->core_actions;
gtk_action_group_set_translation_domain (action_group, domain);
gtk_action_group_add_actions (
action_group, core_entries,
G_N_ELEMENTS (core_entries), editor);
gtk_action_group_add_radio_actions (
action_group, core_justify_entries,
G_N_ELEMENTS (core_justify_entries),
E_HTML_EDITOR_SELECTION_ALIGNMENT_LEFT,
NULL, NULL);
gtk_action_group_add_radio_actions (
action_group, core_mode_entries,
G_N_ELEMENTS (core_mode_entries),
TRUE,
G_CALLBACK (action_mode_cb), editor);
gtk_action_group_add_radio_actions (
action_group, core_style_entries,
G_N_ELEMENTS (core_style_entries),
E_HTML_EDITOR_SELECTION_BLOCK_FORMAT_PARAGRAPH,
NULL, NULL);
gtk_ui_manager_insert_action_group (manager, action_group, 0);
action = gtk_action_group_get_action (action_group, "mode-html");
g_object_bind_property (
view, "html-mode",
action, "current-value",
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
/* Synchronize wiget mode with the buttons */
e_html_editor_view_set_html_mode (view, TRUE);
/* Face Action */
action = e_emoticon_action_new (
"insert-emoticon", _("_Emoticon"),
_("Insert Emoticon"), NULL);
g_object_set (action, "icon-name", "face-smile", NULL);
g_signal_connect (
action, "item-activated",
G_CALLBACK (action_insert_emoticon_cb), editor);
gtk_action_group_add_action (action_group, action);
g_object_unref (action);
/* Core Actions (HTML only) */
action_group = editor->priv->html_actions;
gtk_action_group_set_translation_domain (action_group, domain);
gtk_action_group_add_actions (
action_group, html_entries,
G_N_ELEMENTS (html_entries), editor);
gtk_action_group_add_toggle_actions (
action_group, html_toggle_entries,
G_N_ELEMENTS (html_toggle_entries), editor);
gtk_action_group_add_radio_actions (
action_group, html_size_entries,
G_N_ELEMENTS (html_size_entries),
E_HTML_EDITOR_SELECTION_FONT_SIZE_NORMAL,
NULL, NULL);
gtk_ui_manager_insert_action_group (manager, action_group, 0);
/* Context Menu Actions */
action_group = editor->priv->context_actions;
gtk_action_group_set_translation_domain (action_group, domain);
gtk_action_group_add_actions (
action_group, context_entries,
G_N_ELEMENTS (context_entries), editor);
gtk_ui_manager_insert_action_group (manager, action_group, 0);
/* Context Menu Actions (HTML only) */
action_group = editor->priv->html_context_actions;
gtk_action_group_set_translation_domain (action_group, domain);
gtk_action_group_add_actions (
action_group, html_context_entries,
G_N_ELEMENTS (html_context_entries), editor);
gtk_ui_manager_insert_action_group (manager, action_group, 0);
/* Context Menu Actions (spell check only) */
action_group = editor->priv->spell_check_actions;
gtk_action_group_set_translation_domain (action_group, domain);
gtk_action_group_add_actions (
action_group, spell_context_entries,
G_N_ELEMENTS (spell_context_entries), editor);
gtk_ui_manager_insert_action_group (manager, action_group, 0);
/* Language actions are generated dynamically. */
editor_actions_setup_languages_menu (editor);
action_group = editor->priv->language_actions;
gtk_ui_manager_insert_action_group (manager, action_group, 0);
/* Some spell check actions are generated dynamically. */
action_group = editor->priv->suggestion_actions;
editor_actions_setup_spell_check_menu (editor);
gtk_ui_manager_insert_action_group (manager, action_group, 0);
/* Do this after all language actions are initialized. */
editor_update_static_spell_actions (editor);
/* Fine Tuning */
g_object_set (
G_OBJECT (ACTION (SHOW_FIND)),
"short-label", _("_Find"), NULL);
g_object_set (
G_OBJECT (ACTION (SHOW_REPLACE)),
"short-label", _("Re_place"), NULL);
g_object_set (
G_OBJECT (ACTION (INSERT_IMAGE)),
"short-label", _("_Image"), NULL);
g_object_set (
G_OBJECT (ACTION (INSERT_LINK)),
"short-label", _("_Link"), NULL);
g_object_set (
G_OBJECT (ACTION (INSERT_RULE)),
/* Translators: 'Rule' here means a horizontal line in an HTML text */
"short-label", _("_Rule"), NULL);
g_object_set (
G_OBJECT (ACTION (INSERT_TABLE)),
"short-label", _("_Table"), NULL);
gtk_action_set_sensitive (ACTION (UNINDENT), FALSE);
gtk_action_set_sensitive (ACTION (FIND_AGAIN), FALSE);
gtk_action_set_sensitive (ACTION (SPELL_CHECK), FALSE);
g_object_bind_property (
view, "can-redo",
ACTION (REDO), "sensitive",
G_BINDING_SYNC_CREATE);
g_object_bind_property (
view, "can-undo",
ACTION (UNDO), "sensitive",
G_BINDING_SYNC_CREATE);
g_object_bind_property (
view, "can-copy",
ACTION (COPY), "sensitive",
G_BINDING_SYNC_CREATE);
g_object_bind_property (
view, "can-cut",
ACTION (CUT), "sensitive",
G_BINDING_SYNC_CREATE);
g_object_bind_property (
view, "can-paste",
ACTION (PASTE), "sensitive",
G_BINDING_SYNC_CREATE);
/* This is connected to JUSTIFY_LEFT action only, but
* it automatically applies on all actions in the group. */
g_object_bind_property (
editor->priv->selection, "alignment",
ACTION (JUSTIFY_LEFT), "current-value",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
g_object_bind_property (
editor->priv->selection, "bold",
ACTION (BOLD), "active",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
g_object_bind_property (
editor->priv->selection, "font-size",
ACTION (FONT_SIZE_GROUP), "current-value",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
g_object_bind_property (
editor->priv->selection, "block-format",
ACTION (STYLE_NORMAL), "current-value",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
g_object_bind_property (
editor->priv->selection, "indented",
ACTION (UNINDENT), "sensitive",
G_BINDING_SYNC_CREATE);
g_object_bind_property (
editor->priv->selection, "italic",
ACTION (ITALIC), "active",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
g_object_bind_property (
editor->priv->selection, "monospaced",
ACTION (MONOSPACED), "active",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
g_object_bind_property (
editor->priv->selection, "strikethrough",
ACTION (STRIKETHROUGH), "active",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
g_object_bind_property (
editor->priv->selection, "underline",
ACTION (UNDERLINE), "active",
G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
/* Disable all actions and toolbars when editor is not editable */
g_object_bind_property (
view, "editable",
editor->priv->core_actions, "sensitive",
G_BINDING_SYNC_CREATE);
g_object_bind_property (
view, "editable",
editor->priv->html_actions, "sensitive",
G_BINDING_SYNC_CREATE);
g_object_bind_property (
view, "editable",
editor->priv->spell_check_actions, "sensitive",
G_BINDING_SYNC_CREATE);
g_object_bind_property (
view, "editable",
editor->priv->suggestion_actions, "sensitive",
G_BINDING_SYNC_CREATE);
settings = g_settings_new ("org.gnome.evolution.mail");
gtk_action_set_visible (
ACTION (WEBKIT_INSPECTOR),
g_settings_get_boolean (settings, "composer-developer-mode"));
g_object_unref (settings);
}