[evolution/webkit-composer-rebased: 17/105] Port HTML/plain text mode toggling



commit eb77cae4c5a5bb8748e0aa493ec175634d892497
Author: Dan VrÃtil <dvratil redhat com>
Date:   Tue Jul 31 15:54:49 2012 +0200

    Port HTML/plain text mode toggling
    
    Unlike with GtkHTML, we can't change renderers and make WebKit to
    render HTML code as plain text. The only way is to discard any formatting
    when toggling from HTML to plain text. This is similar to what KMail does.

 e-util/e-editor-actions.c |  143 ++++++++++++++++++++++++++------------------
 e-util/e-editor-widget.c  |   65 ++++++++++++++-------
 e-util/e-editor-widget.h  |    7 +-
 e-util/test-editor.c      |    8 +-
 4 files changed, 136 insertions(+), 87 deletions(-)
---
diff --git a/e-util/e-editor-actions.c b/e-util/e-editor-actions.c
index 94e5702..d030028 100644
--- a/e-util/e-editor-actions.c
+++ b/e-util/e-editor-actions.c
@@ -885,80 +885,102 @@ action_language_cb (GtkToggleAction *action,
 	*/
 }
 
-static void
-action_mode_cb (GtkRadioAction *action,
-                GtkRadioAction *current,
-                EEditor *editor)
+struct _ModeChanged {
+	GtkRadioAction *action;
+	EEditor *editor;
+};
+
+static gboolean
+mode_changed (struct _ModeChanged *data)
 {
-	/* FIXME WEBKIT */
-	/*
 	GtkActionGroup *action_group;
-	HTMLPainter *new_painter;
-	HTMLPainter *old_painter;
-	GtkHTML *html;
-	EditorMode mode;
-	gboolean html_mode;
+	EEditor *editor = data->editor;
+	EEditorWidget *widget;
+	EEditorWidgetMode mode;
+	gboolean is_html;
 
-	html = gtkhtml_editor_get_html (editor);
-	mode = gtk_radio_action_get_current_value (current);
-	html_mode = (mode == EDITOR_MODE_HTML);
+	widget = e_editor_get_editor_widget (editor);
+	mode = gtk_radio_action_get_current_value (data->action);
+	is_html = (mode == E_EDITOR_WIDGET_MODE_HTML);
+
+	if (mode == e_editor_widget_get_mode (widget)) {
+		goto exit;
+	}
+
+	/* If switching from HTML to plain text */
+	if (!is_html) {
+		GtkWidget *dialog, *parent;
+
+		parent = gtk_widget_get_toplevel (GTK_WIDGET (editor));
+		if (!GTK_IS_WINDOW (parent)) {
+			parent = NULL;
+		}
+
+		dialog = gtk_message_dialog_new (
+				parent ? GTK_WINDOW (parent) : NULL,
+				GTK_DIALOG_DESTROY_WITH_PARENT,
+				GTK_MESSAGE_WARNING,
+				GTK_BUTTONS_OK_CANCEL,
+				_("Turning HTML mode off will cause the text "
+				  "to loose all formatting. Do you want to continue?"));
+		if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_CANCEL) {
+			gtk_radio_action_set_current_value (
+				data->action, E_EDITOR_WIDGET_MODE_HTML);
+			gtk_widget_destroy (dialog);
+			goto exit;
+		}
+
+		gtk_widget_destroy (dialog);
+	}
 
 	action_group = editor->priv->html_actions;
-	gtk_action_group_set_sensitive (action_group, html_mode);
+	gtk_action_group_set_sensitive (action_group, is_html);
 
 	action_group = editor->priv->html_context_actions;
-	gtk_action_group_set_visible (action_group, html_mode);
+	gtk_action_group_set_visible (action_group, is_html);
 
-	gtk_widget_set_sensitive (editor->priv->color_combo_box, html_mode);
+	gtk_widget_set_sensitive (editor->priv->color_combo_box, is_html);
 
-	if (html_mode)
+	if (is_html) {
 		gtk_widget_show (editor->priv->html_toolbar);
-	else
+	} else {
 		gtk_widget_hide (editor->priv->html_toolbar);
+	}
 
-	// Certain paragraph styles are HTML-only.
-	gtk_action_set_sensitive (ACTION (STYLE_H1), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H2), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H3), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H4), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H5), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_H6), html_mode);
-	gtk_action_set_sensitive (ACTION (STYLE_ADDRESS), html_mode);
+	/* Certain paragraph styles are HTML-only. */
+	gtk_action_set_sensitive (ACTION (STYLE_H1), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H2), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H3), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H4), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H5), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_H6), is_html);
+	gtk_action_set_sensitive (ACTION (STYLE_ADDRESS), is_html);
 
-	// Swap painters.
+	e_editor_widget_set_mode (
+		e_editor_get_editor_widget (editor), mode);
 
-	if (html_mode) {
-		new_painter = editor->priv->html_painter;
-		old_painter = editor->priv->plain_painter;
-	} else {
-		new_painter = editor->priv->plain_painter;
-		old_painter = editor->priv->html_painter;
-	}
+ exit:
+	g_clear_object (&data->editor);
+	g_clear_object (&data->action);
+	g_free (data);
 
-	// Might be true during initialization.
-	if (html->engine->painter == new_painter)
-		return;
+	return FALSE;
+}
 
-	html_gdk_painter_unrealize (HTML_GDK_PAINTER (old_painter));
-	if (html->engine->window != NULL)
-		html_gdk_painter_realize (
-			HTML_GDK_PAINTER (new_painter),
-			html->engine->window);
-
-	html_font_manager_set_default (
-		&new_painter->font_manager,
-		old_painter->font_manager.variable.face,
-		old_painter->font_manager.fixed.face,
-		old_painter->font_manager.var_size,
-		old_painter->font_manager.var_points,
-		old_painter->font_manager.fix_size,
-		old_painter->font_manager.fix_points);
-
-	html_engine_set_painter (html->engine, new_painter);
-	html_engine_schedule_redraw (html->engine);
-
-	g_object_notify (G_OBJECT (editor), "html-mode");
-	*/
+static void
+action_mode_cb (GtkRadioAction *action,
+                GtkRadioAction *current,
+                EEditor *editor)
+{
+	struct _ModeChanged *data;
+
+	data = g_new0 (struct _ModeChanged, 1);
+	data->action = g_object_ref (current);
+	data->editor = g_object_ref (editor);
+
+	/* We can't change group current value from this callback, so
+	 * let's do it all from an idle callback */
+	g_idle_add ((GSourceFunc) mode_changed, data);
 }
 
 static void
@@ -2130,6 +2152,7 @@ editor_actions_init (EEditor *editor)
 
 	manager = e_editor_get_ui_manager (editor);
 	domain = GETTEXT_PACKAGE;
+	editor_widget = e_editor_get_editor_widget (editor);
 
 	/* Core Actions */
 	action_group = editor->priv->core_actions;
@@ -2154,6 +2177,9 @@ editor_actions_init (EEditor *editor)
 		G_CALLBACK (action_style_cb), editor);
 	gtk_ui_manager_insert_action_group (manager, action_group, 0);
 
+	/* Synchronize wiget mode with the button */
+	e_editor_widget_set_mode (editor_widget, E_EDITOR_WIDGET_MODE_HTML);
+
 	/* Face Action */
 	action = e_emoticon_action_new (
 		"insert-face", _("_Emoticon"),
@@ -2239,7 +2265,6 @@ editor_actions_init (EEditor *editor)
 	gtk_action_set_sensitive (ACTION (UNINDENT), FALSE);
 	gtk_action_set_sensitive (ACTION (FIND_AGAIN), FALSE);
 
-	editor_widget = e_editor_get_editor_widget (editor);
 	g_object_bind_property (
 		editor_widget, "can-redo",
 		ACTION (REDO), "sensitive",
diff --git a/e-util/e-editor-widget.c b/e-util/e-editor-widget.c
index 7930595..4951221 100644
--- a/e-util/e-editor-widget.c
+++ b/e-util/e-editor-widget.c
@@ -21,12 +21,12 @@
 #endif
 
 #include "e-editor-widget.h"
+#include "e-editor.h"
 
 #include <glib/gi18n-lib.h>
 
 struct _EEditorWidgetPrivate {
 	gint changed		: 1;
-	gint html_mode		: 1;
 	gint inline_spelling	: 1;
 	gint magic_links	: 1;
 	gint magic_smileys	: 1;
@@ -36,6 +36,8 @@ struct _EEditorWidgetPrivate {
 	gint can_redo		: 1;
 	gint can_undo		: 1;
 
+	EEditorWidgetMode mode;
+
 	/* FIXME WEBKIT Is this in widget's competence? */
 	GList *spelling_langs;
 };
@@ -49,7 +51,7 @@ G_DEFINE_TYPE (
 enum {
 	PROP_0,
 	PROP_CHANGED,
-	PROP_HTML_MODE,
+	PROP_MODE,
 	PROP_INLINE_SPELLING,
 	PROP_MAGIC_LINKS,
 	PROP_MAGIC_SMILEYS,
@@ -61,6 +63,22 @@ enum {
 	PROP_CAN_UNDO
 };
 
+static void
+editor_widget_strip_formatting (EEditorWidget *widget)
+{
+	gchar *plain, *html;
+
+	plain = e_editor_widget_get_text_plain (widget);
+
+	/* Convert \n to <br> */
+	regex = g_regex_new ("\n", 0, 0, NULL);
+	html = g_regex_replace (regex, plain, strlen (plain), 0, "<br>", 0, NULL);
+
+	e_editor_widget_set_text_html (widget, html);
+
+	g_free (plain);
+	g_free (html);
+}
 
 static void
 editor_widget_user_changed_contents_cb (EEditorWidget *widget,
@@ -116,9 +134,9 @@ e_editor_widget_get_property (GObject *object,
 {
 	switch (property_id) {
 
-		case PROP_HTML_MODE:
-			g_value_set_boolean (
-				value, e_editor_widget_get_html_mode (
+		case PROP_MODE:
+			g_value_set_int (
+				value, e_editor_widget_get_mode (
 				E_EDITOR_WIDGET (object)));
 			return;
 
@@ -182,10 +200,10 @@ e_editor_widget_set_property (GObject *object,
 {
 	switch (property_id) {
 
-		case PROP_HTML_MODE:
-			e_editor_widget_set_html_mode (
+		case PROP_MODE:
+			e_editor_widget_set_mode (
 				E_EDITOR_WIDGET (object),
-				g_value_get_boolean (value));
+				g_value_get_int (value));
 			return;
 
 		case PROP_INLINE_SPELLING:
@@ -234,12 +252,14 @@ e_editor_widget_class_init (EEditorWidgetClass *klass)
 
 	g_object_class_install_property (
 		object_class,
-		PROP_HTML_MODE,
-		g_param_spec_boolean (
-			"html-mode",
-			"HTML Mode",
+		PROP_MODE,
+		g_param_spec_int (
+			"mode",
+			"Mode",
 			"Edit HTML or plain text",
-			TRUE,
+			E_EDITOR_WIDGET_MODE_PLAIN_TEXT,
+		    	E_EDITOR_WIDGET_MODE_HTML,
+		    	E_EDITOR_WIDGET_MODE_PLAIN_TEXT,
 			G_PARAM_READWRITE |
 			G_PARAM_CONSTRUCT));
 
@@ -414,26 +434,29 @@ e_editor_widget_set_changed (EEditorWidget *widget,
 	g_object_notify (G_OBJECT (widget), "changed");
 }
 
-gboolean
-e_editor_widget_get_html_mode (EEditorWidget *widget)
+EEditorWidgetMode
+e_editor_widget_get_mode (EEditorWidget *widget)
 {
 	g_return_val_if_fail (E_IS_EDITOR_WIDGET (widget), FALSE);
 
-	return widget->priv->html_mode;
+	return widget->priv->mode;
 }
 
 void
-e_editor_widget_set_html_mode (EEditorWidget *widget,
-			       gboolean html_mode)
+e_editor_widget_set_mode (EEditorWidget *widget,
+			  EEditorWidgetMode mode)
 {
 	g_return_if_fail (E_IS_EDITOR_WIDGET (widget));
 
-	if ((widget->priv->html_mode ? TRUE : FALSE) == (html_mode ? TRUE : FALSE))
+	if (widget->priv->mode == mode)
 		return;
 
-	widget->priv->html_mode = html_mode;
+	widget->priv->mode = mode;
+
+	if (widget->priv->mode == E_EDITOR_WIDGET_MODE_PLAIN_TEXT)
+		editor_widget_strip_formatting (widget);
 
-	g_object_notify (G_OBJECT (widget), "html-mode");
+	g_object_notify (G_OBJECT (widget), "mode");
 }
 
 gboolean
diff --git a/e-util/e-editor-widget.h b/e-util/e-editor-widget.h
index 0ed03c0..0affadf 100644
--- a/e-util/e-editor-widget.h
+++ b/e-util/e-editor-widget.h
@@ -86,9 +86,10 @@ gboolean	e_editor_widget_get_changed	(EEditorWidget *widget);
 void		e_editor_widget_set_changed	(EEditorWidget *widget,
 						 gboolean changed);
 
-gboolean	e_editor_widget_get_html_mode	(EEditorWidget *widget);
-void		e_editor_widget_set_html_mode	(EEditorWidget *widget,
-						 gboolean html_mode);
+EEditorWidgetMode
+		e_editor_widget_get_mode	(EEditorWidget *widget);
+void		e_editor_widget_set_mode	(EEditorWidget *widget,
+						 EEditorWidgetMode mode);
 
 gboolean	e_editor_widget_get_inline_spelling
 						(EEditorWidget *widget);
diff --git a/e-util/test-editor.c b/e-util/test-editor.c
index 00635a3..8cac737 100644
--- a/e-util/test-editor.c
+++ b/e-util/test-editor.c
@@ -217,8 +217,8 @@ action_save_cb (GtkAction *action,
 			return;
 
 	filename = e_editor_get_filename (editor);
-	as_html = e_editor_widget_get_html_mode (
-			e_editor_get_editor_widget (editor));
+	as_html = (e_editor_widget_get_mode (
+			e_editor_get_editor_widget (editor)) == E_EDITOR_WIDGET_MODE_HTML);
 
 	e_editor_save (editor, filename, as_html, &error);
 	handle_error (&error);
@@ -236,8 +236,8 @@ action_save_as_cb (GtkAction *action,
 		return;
 
 	filename = e_editor_get_filename (editor);
-	as_html = e_editor_widget_get_html_mode (
-			e_editor_get_editor_widget (editor));
+	as_html = (e_editor_widget_get_mode (
+			e_editor_get_editor_widget (editor)) == E_EDITOR_WIDGET_MODE_HTML);
 
 	e_editor_save (editor, filename, as_html, &error);
 	handle_error (&error);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]